framework_eng/rules/yaxunit-isolation/SKILL.md
For DB-writing YaxUnit tests, use 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.
Trigger: a server test (
ДобавитьСерверныйТест) writes to the DB — it creates, posts, modifies, and deletes objects. When this happens, apply thetest-writingskill (framework/skills/bsl-practices/test-writing/SKILL.md), section "Isolating test data".
A test that writes to the DB must roll back its changes — otherwise each run leaves garbage in the database, tests become non-idempotent, and the database gradually degrades. YaxUnit solves this with the built-in .ВТранзакции() mechanism: before each test, a transaction is opened; after the test, it is rolled back.
| Requirement | Description |
|---|---|
| .ВТранзакции() by default | Any set of server tests that write to the DB is registered with .ВТранзакции() immediately after ДобавитьТестовыйНабор() |
| Catalogs via ЮТест.Данные() | Create catalog items only through ЮТест.Данные().СоздатьЭлемент(...) or КонструкторОбъекта(...).Записать() — then they are tracked and removed automatically |
| Exception -> explicit rationale | A set without .ВТранзакции() MUST contain a comment before ДобавитьТестовыйНабор() stating the reason for the exception (one of the three below) + teardown via .После("ИмяПроцедурыОчистки") |
| Documents without .ВТранзакции() -> teardown | Documents created via Документы.X.СоздатьДокумент() (not via ЮТест.Данные()) are NOT tracked by auto-cleanup — they require explicit teardown in .После() |
| Client tests - without .ВТранзакции() | ДобавитьКлиентскийТест runs in the client context, where transactional rollback is unavailable |
.ВТранзакции()The test checks that posting a document is forbidden (Отказ = Истина is set in the handler). A nested write transaction with an error poisons the outer one: subsequent reads return "Errors have already occurred in this transaction!". The solution is not to wrap such sets in .ВТранзакции(), to create objects via ЮТест.Данные() (they will be removed by .УдалениеТестовыхДанных()), and to additionally clean up the document in teardown.
// Исключение (а): негативный тест проведения — ожидаемый Отказ отравляет внешнюю транзакцию.
// Изоляция через ЮТест.Данные() + .УдалениеТестовыхДанных() + teardown в .После().
ЮТТесты
.ДобавитьТестовыйНабор("Запрет проведения без договора")
.УдалениеТестовыхДанных()
.После("ОчиститьДокументыЗапретПроведения")
.ДобавитьСерверныйТест("ТестЗапретБезДоговора");
ТранзакцияАктивна() guardSome production procedures explicitly check for the absence of an active transaction (two-phase commits, real external API calls, writes to information registers with a unique key). Running such code inside .ВТранзакции() causes an error or unexpected behavior in the production code itself.
// Исключение (б): прод-код содержит гвард ТранзакцияАктивна() — нельзя запускать в транзакции.
// Teardown выполняет ручную очистку через ЮТест.Данные().УстановитьЗначениеРеквизита().
ЮТТесты
.ДобавитьТестовыйНабор("Двухфазная фиксация позиции")
.После("ОчиститьДанныеДвухфазнойФиксации")
.ДобавитьСерверныйТест("ТестФиксацияПозиции");
ДобавитьКлиентскийТест — transactional rollback on the client is unavailable by platform architecture. Test data under client tests is created and cleaned through Перед/После handlers in the server context.
A test that changes the document write mode (posting -> unposting -> reposting) must reread the object between mode changes via ДокОбъект = Ссылка.ПолучитьОбъект() — this mirrors form behavior:
// Провести
ДокОбъект = ДокСсылка.ПолучитьОбъект();
ДокОбъект.Записать(РежимЗаписиДокумента.Проведение);
// Отменить проведение — перечитываем, как это делает форма
ДокОбъект = ДокСсылка.ПолучитьОбъект();
ДокОбъект.Записать(РежимЗаписиДокумента.ОтменаПроведения);
// Снова провести — перечитываем ещё раз
ДокОбъект = ДокСсылка.ПолучитьОбъект();
ДокОбъект.Записать(РежимЗаписиДокумента.Проведение);
Important (platform 8.3.27): programmatic reposting in a server session can trigger a platform error [ОшибкаХранимыхДанных] (stack without application frames). Neither rereading nor .ВТранзакции() fixes it — this is a platform limitation. In this case, reposting idempotence is checked at the scenario layer (Vanessa, path through the form), and the unit test is written with ЮТест.Пропустить() and an explicit rationale.
.ВТранзакции()Процедура ИсполняемыеСценарии() Экспорт
ЮТТесты
// Стандартный пишущий набор — транзакционная изоляция по умолчанию
.ДобавитьТестовыйНабор("Проведение документа")
.ВТранзакции()
.ДобавитьСерверныйТест("ТестПроведениеСДоговором")
.ДобавитьСерверныйТест("ТестПроведениеСКорректнойСуммой")
// Исключение (а): негативный тест — ожидаемый Отказ
// Исключение (а): вложенная транзакция с Отказ отравляет внешнюю.
.ДобавитьТестовыйНабор("Запрет проведения")
.УдалениеТестовыхДанных()
.После("ОчиститьЗапретПроведения")
.ДобавитьСерверныйТест("ТестЗапретБезДоговора");
КонецПроцедуры
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.