framework/rules/yaxunit-isolation/SKILL.md
Для DB-writing YaxUnit tests использовать transaction
npx skillsauth add steelmorgan/1c-agent-based-dev-framework yaxunit-isolationInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Триггер: серверный тест (
ДобавитьСерверныйТест) обращается к БД на запись — создаёт, проводит, изменяет, удаляет объекты. При срабатывании — применить навыкtest-writing(framework/skills/bsl-practices/test-writing/SKILL.md), раздел «Изоляция тестовых данных».
Тест, пишущий в БД, обязан откатывать свои изменения — иначе каждый прогон оставляет мусор в базе, тесты становятся неидемпотентными, а база постепенно деградирует. YaxUnit решает это через встроенный механизм .ВТранзакции(): перед каждым тестом открывается транзакция, после теста — откатывается.
| Требование | Описание |
|---|---|
| .ВТранзакции() по умолчанию | Любой набор серверных тестов, пишущих в БД, регистрируется с .ВТранзакции() сразу после ДобавитьТестовыйНабор() |
| Справочники — через ЮТест.Данные() | Создание элементов справочников только через ЮТест.Данные().СоздатьЭлемент(...) или КонструкторОбъекта(...).Записать() — тогда они трекаются и удаляются автоматически |
| Исключение → явное обоснование | Набор без .ВТранзакции() ОБЯЗАН содержать комментарий перед ДобавитьТестовыйНабор() с указанием причины исключения (одна из трёх ниже) + teardown через .После("ИмяПроцедурыОчистки") |
| Документы без .ВТранзакции() → teardown | Документы, создаваемые через Документы.X.СоздатьДокумент() (не через ЮТест.Данные()), НЕ трекаются автоочисткой — требуют явного teardown в .После() |
| Клиентские тесты — без .ВТранзакции() | ДобавитьКлиентскийТест выполняется в клиентском контексте, где транзакционный откат недоступен |
.ВТранзакции()Тест проверяет, что проведение документа запрещается (устанавливается Отказ = Истина в обработчике). Вложенная транзакция записи с ошибкой отравляет внешнюю: последующие чтения дают «В данной транзакции уже происходили ошибки!». Решение — не оборачивать такие наборы в .ВТранзакции(), создавать объекты через ЮТест.Данные() (они будут удалены по .УдалениеТестовыхДанных()) и дополнительно зачищать документ в teardown.
// Исключение (а): негативный тест проведения — ожидаемый Отказ отравляет внешнюю транзакцию.
// Изоляция через ЮТест.Данные() + .УдалениеТестовыхДанных() + teardown в .После().
ЮТТесты
.ДобавитьТестовыйНабор("Запрет проведения без договора")
.УдалениеТестовыхДанных()
.После("ОчиститьДокументыЗапретПроведения")
.ДобавитьСерверныйТест("ТестЗапретБезДоговора");
ТранзакцияАктивна()Некоторые прод-процедуры явно проверяют отсутствие активной транзакции (двухфазные фиксации, реальные вызовы внешнего API, записи в регистры сведений с уникальным ключом). Запуск такого кода внутри .ВТранзакции() вызывает ошибку или неожиданное поведение в самом прод-коде.
// Исключение (б): прод-код содержит гвард ТранзакцияАктивна() — нельзя запускать в транзакции.
// Teardown выполняет ручную очистку через ЮТест.Данные().УстановитьЗначениеРеквизита().
ЮТТесты
.ДобавитьТестовыйНабор("Двухфазная фиксация позиции")
.После("ОчиститьДанныеДвухфазнойФиксации")
.ДобавитьСерверныйТест("ТестФиксацияПозиции");
ДобавитьКлиентскийТест — транзакционный откат на клиенте недоступен по архитектуре платформы. Тестовые данные под клиентскими тестами создаются и чистятся через Перед/После-обработчики в серверном контексте.
Тест, который меняет режим записи документа (проведение → отмена проведения → повторное проведение), обязан перечитывать объект между сменами через ДокОбъект = Ссылка.ПолучитьОбъект() — это моделирует поведение формы:
// Провести
ДокОбъект = ДокСсылка.ПолучитьОбъект();
ДокОбъект.Записать(РежимЗаписиДокумента.Проведение);
// Отменить проведение — перечитываем, как это делает форма
ДокОбъект = ДокСсылка.ПолучитьОбъект();
ДокОбъект.Записать(РежимЗаписиДокумента.ОтменаПроведения);
// Снова провести — перечитываем ещё раз
ДокОбъект = ДокСсылка.ПолучитьОбъект();
ДокОбъект.Записать(РежимЗаписиДокумента.Проведение);
Важно (платформа 8.3.27): программное перепроведение в серверной сессии может вызвать платформенную ошибку [ОшибкаХранимыхДанных] (стек без прикладных кадров). Ни перечитывание, ни .ВТранзакции() её не устраняют — это ограничение платформы. В таком случае идемпотентность перепроведения проверяется сценарным слоем (Vanessa, путь через форму), а юнит-тест пишется с ЮТест.Пропустить() и явным обоснованием.
.ВТранзакции()Процедура ИсполняемыеСценарии() Экспорт
ЮТТесты
// Стандартный пишущий набор — транзакционная изоляция по умолчанию
.ДобавитьТестовыйНабор("Проведение документа")
.ВТранзакции()
.ДобавитьСерверныйТест("ТестПроведениеСДоговором")
.ДобавитьСерверныйТест("ТестПроведениеСКорректнойСуммой")
// Исключение (а): негативный тест — ожидаемый Отказ
// Исключение (а): вложенная транзакция с Отказ отравляет внешнюю.
.ДобавитьТестовыйНабор("Запрет проведения")
.УдалениеТестовыхДанных()
.После("ОчиститьЗапретПроведения")
.ДобавитьСерверныйТест("ТестЗапретБезДоговора");
КонецПроцедуры
depends_on:
development
1C server maintenance webhooks: container restart and external component cache cleanup
development
Interactive DAP debugging of a single BSL procedure
tools
Rules for using RLM tools for project search and navigation in 1C/BSL
development
Creates web applications and routes on Winow (a web server on OneScript and Autumn). Use when working with a web server on OneScript, routing, or Winow controllers.