Воспроизводимая линия разработки на 1С: почему окружение надо фиксировать, а не описывать

13.08.26

Разработка - Тестирование QA

Написать тест на 1С несложно. Дорого стоит привести базу в состояние, где прогон вообще стартует: семь шагов, каждый ломает запуск молча — без ошибки, без записи в журнале. И эту цену платит заново каждый новый человек на проекте. Разбираю молчаливый отказ окружения как класс проблем, показываю, почему его не закрывают ни документация, ни скрипт развёртывания, и предлагаю решение — фиксацию состояния в артефакте с машинно-проверяемым критерием приёмки. Подход проверен на сквозной задаче (первая задача экзамена «1С:Специалист по платформе» с юнит- и функциональными тестами), а затем перенесён на пул тестовых баз с типовыми конфигурациями. Отдельно — каталог симптомов и их настоящих причин, который пригодится независимо от инструментария.

Дорого стоят не тесты

YAxUnit ставится за несколько минут, синтаксис теста читается без документации, первый тест на общий модуль пишется за четверть часа. Проблема начинается не здесь.

Запускаем прогон в пакетном режиме:

1cv8.exe ENTERPRISE /F "путь_к_базе" /N admin /CRunUnitTests=run.json

Вместо прогона открывается обычное окно конфигурации. Ни ошибки, ни предупреждения. В логе платформы пусто. В журнале регистрации — ни одной записи уровня «Ошибка».

Проверяем конфигурационный файл — валиден. Проверяем расширение — платформа показывает Активно = Да. Проверяем права — полные. И всё равно ничего не происходит.

За одну сессию я поймал четыре независимые причины такого поведения. Каждая по отдельности полностью блокирует прогон, и ни одна не даёт диагностического сообщения. Пока не устранены все четыре, наблюдаемое поведение одинаково: приложение открывается, каталог отчёта пуст.

Это не рассказ о невезении, а замер стоимости входа. Несколько часов уходит не на работу, а на выяснение того, что ничего не сломано — окружение просто собрано не до конца. И самое неприятное свойство этой цены: её платит каждый новый человек на проекте, заново и в одиночку. Знание о семи шагах живёт в голове того, кто их уже прошёл, и не переносится ни коммитом, ни ревью.

Именно из этого наблюдения выросло решение, о котором пойдёт речь. Оно касается не тестирования, а того, как вообще хранить состояние рабочего окружения.


Диагноз: это класс проблем, а не набор случаев

Механизм у всех четырёх причин один. Разбор параметров запуска обёрнут в Попытка, и при любом сбое YAxUnit молча откатывается на настройки по умолчанию. В умолчаниях reportPath пустой — отчёт писать некуда. Исключение не выбрасывается, в журнал ничего не пишется.

Отсюда формулируется класс:

Любое окружение, где неверная конфигурация неотличима от верной по наблюдаемому поведению, порождает молчаливые отказы.

YAxUnit здесь — только повод. Тот же класс дают:

  • BOM в JSON-конфиге. Файл открывается, глазами выглядит нормально, json.load падает — и мост перестаёт видеть все базы разом, а не одну испорченную.
  • Отсутствие BOM в .ps1. PowerShell 5.1 читает кириллицу как ANSI и сообщает «Unexpected token» на строке, которая выглядит безупречно.
  • Аргумент с пробелом, склеенный в один. Платформа сообщает «Отсутствует файл базы данных 'Z:\1Cv8.1CD'» — про базу, которую никто не просил открывать.
  • Загруженное, но не применённое расширение. Список расширений показывает Активно = Да, код при этом не работает.

Есть и более коварный подвид: диагностика существует, но выводится только на экран. Расширение, подключённое в безопасном режиме, честно сообщает «Расширение подключено в безопасном режиме. Чтение конфигурационного файла недоступно» — но в пакетном режиме на экран никто не смотрит. Снаружи это неотличимо от зависшего прогона: процесс жив, файл базы пишется, отчёта нет.

По времени такое тоже не опознать. Первый запуск свежевосстановленной демо-базы сам по себе тянет штатное обновление ИБ около минуты — ровно похоже на ожидание у диалога. Различать приходится по косвенному признаку: при этой ошибке лог прогона не создаётся вовсе.

Общее у всех: симптом не указывает на причину, а иногда указывает на ложную. Диагностика превращается в перебор гипотез, и её длительность зависит от везения.

С таким классом бесполезно бороться внимательностью. Внимательность — это ресурс, который тратится каждый раз заново и заканчивается к вечеру пятницы.


Почему привычные средства не закрывают проблему

Прежде чем предлагать решение, честно разберу те, что напрашиваются первыми.

 

Средство Почему недостаточно
Чеклист в вики Устаревает молча. Читается после ошибки, а не до. Никто не проверяет, что он ещё актуален
Скрипт развёртывания Воспроизводит семь шагов каждый раз, ломается на любом из них, сам требует поддержки
«Спроси коллегу, он настраивал» Не переживает отпуск, увольнение и смену проекта
Инструкция в README То же, что чеклист, только с иллюзией версионирования

 

Отдельно про скрипт — он выглядит самым разумным вариантом и потому заслуживает разбора.

Скрипт описывает путь. Каждый его запуск — это семь шансов сломаться: обновилась платформа, изменился формат конфига, диалог безопасности появился там, где его не было. Скрипт при этом сам становится объектом поддержки: его надо чинить, тестировать и версионировать. Мы заменили одну хрупкую последовательность на другую, чуть более автоматизированную.

Причём проверить скрипт по-настоящему можно только одним способом — выполнить его и посмотреть на результат. То есть всё равно проверяется точка прибытия, а не маршрут.

Отсюда решение: если проверяется прибытие, то и хранить надо прибытие.

Оговорюсь сразу — это верно там, где прибытие можно заморозить. Есть случаи, где нельзя, и тогда скрипт возвращается в игру, но уже с дополнительными требованиями к себе. Разберу их в разделе о границах применимости.


Решение: состояние как артефакт

Вот те семь шагов, которые нужно выполнить, чтобы прогон в принципе стартовал:

  1. Создать базу и загрузить конфигурацию.
  2. Создать роль с системными правами.
  3. Завести пользователя ИБ с этой ролью и снять защиту от опасных действий (способа два, см. ниже).
  4. Загрузить YAxUnit и применить его (это разные операции).
  5. Снять «Безопасный режим» у расширений.
  6. Убедиться, что в конфигурации есть ПриНачалеРаботыСистемы() без параметров.
  7. Проверить, что расширения реально подключены в сеансе.

Все семь одинаковы для любой задачи и не зависят от предметной области. Значит, они выполняются один раз, а результат сохраняется как .dt-слепок.

Дальше новая база создаётся одной командой и сразу готова к прогону тестов.

Что внутри эталона

Снятая защита от опасных действий. Иначе любая служебная обработка вешает модальный диалог, который в пакетном режиме подтвердить нельзя — процесс висит до таймаута. Способов два, и они относятся к разным уровням:

  • флаг у пользователя ИБ — свойство конкретной базы, попадает в .dt вместе с ней;
  • маска в conf.cfg платформы — свойство установки, действует на все базы, чья строка соединения подходит под регулярное выражение:
DisableUnsafeActionProtection=.*TestBases.*

Для одиночной базы проще первый способ. Для каталога с тестовыми базами — второй: он ловит все базы разом, переживает добавление новых и не требует заходить внутрь каждой. Проверено на демо-базе с пользователями, у которых флаг не снимался: три прогона внешней обработки подряд, ни одного диалога.

Это не отменяет отдельного шага для расширений — безопасный режим расширения живёт внутри базы и маской не снимается (подробнее ниже, в каталоге отказов).

Роль с системными правами и флагом «Устанавливать права для новых объектов». Второе важнее первого: без него роль приходится дописывать после каждого нового справочника. С ним объектные права не перечисляются вовсе — они выдаются автоматически.

Модуль управляемого приложения с пустой процедурой:

Процедура ПриНачалеРаботыСистемы()
	// Пустая намеренно: это точка расширения, за которую цепляется YAxUnit
	// через &После("ПриНачалеРаботыСистемы") в своём модуле приложения.
КонецПроцедуры

Каркасные конфигурации модуля приложения не имеют вовсе — а без него перехватчику не за что зацепиться.

Режим совместимости не ниже 8.3.27. На 8.3.17 механизм расширения модуля управляемого приложения не работает, и тесты не запускаются.

YAxUnit, загруженный и применённый, со снятым безопасным режимом.

Чем за это приходится платить

Решение не бесплатное, и делать вид, что это не так, — плохая услуга читателю.

  • .dt бинарный: диффа не видно, ревью содержимого невозможно, конфликты слияния не разрешаются.
  • Нужен Git LFS — репозиторий растёт, обычным git clone без настроенного LFS слепок не получить.
  • Эталон привязан к версии платформы и требует пересборки при её смене.
  • Состав эталона — отдельное решение, которое надо ревизовать: добавилось требование к окружению — эталон устарел.

Это принимается сознательно, потому что альтернатива дороже: семь ручных шагов на каждого нового человека, каждый из которых ломается молча.

Проверка, что эталон живой

.dt переносит всё перечисленное целиком, включая применённые расширения и настройки пользователя. Это не предположение: слепок развёрнут в чистую базу, прогон стартовал и записал отчёт с exitCode = 0.

О том, почему критерий приёмки сформулирован именно так, — отдельный раздел ниже.


Что получилось в итоге: линия

Не фреймворк и не продукт. Набор соглашений и артефактов, который превращает путь от постановки задачи до зелёных тестов в предсказуемую последовательность.

Вход: текст постановки задачи.

Выход: работающая конфигурация, junit.xml с exitCode = 0 и отчёт функциональных тестов.

 

Стадия Чем закрыта
Новая база «под ключ» эталонный .dt — одна команда
Метаданные из описания генераторы из JSON-описаний
Загрузка и проверка пакетный режим конфигуратора
Модульные тесты YAxUnit
Функциональные тесты Vanessa Automation
Перенос и версионирование Git + LFS

 

 

Схема стадий линии: от постановки до зелёных тестов

Объекты создаются из JSON-описаний, а не руками в конфигураторе. Регистр накопления целиком:

{
  "type": "AccumulationRegister",
  "name": "ОстаткиНоменклатуры",
  "registerType": "Balance",
  "dimensions": [
    "Подразделение: CatalogRef.Подразделения | master, mainFilter",
    "Номенклатура: CatalogRef.Номенклатура | req",
    "Характеристика: CatalogRef.ХарактеристикиНоменклатуры",
    "Партия: DocumentRef.ПриходнаяНакладная + DocumentRef.Сборка"
  ],
  "resources": ["Количество: Number(15,3)", "Сумма: Number(15,2)"]
}

Такое описание версионируется, ревьюится в merge request и читается за десять секунд — в отличие от XML-выгрузки того же объекта на несколько сотен строк.

Тесты — двух уровней. YAxUnit проверяет бизнес-логику напрямую, Vanessa Automation — работу через интерфейс. Оба нужны: юнит-тест не поймает сломанную форму, а сценарий через интерфейс слишком дорог для перебора вариантов расчёта.


Контракты вместо договорённостей

Это принципиальный момент, из которого следует всё остальное.

Между стадиями передаются файлы с однозначными контрактами:

постановка → JSON метаданных → XML исходников → BSL модулей
           → тестовый модуль → junit.xml → вердикт

Ни одна стадия не полагается на «мы же выше договорились». Каждая получает на вход артефакт, который можно прочитать, проверить и передать дальше.

Главное следствие: контракт переживает исполнителя. Стадию можно отдать другому разработчику, другой модели или в CI — формат входа и выхода не изменится. Договорённость, живущая в переписке, так не умеет.

Отсюда ещё два полезных свойства.

Ошибка локализуется. Если junit.xml не сформировался, проблема между «тестами» и «прогоном», а не «где-то в процессе».

Подход переносим. Конкретные генераторы у вас могут быть другими, но JSON-описание объекта, чеклист готовности базы и формат отчёта — универсальны.


Критерий приёмки: проверяемый или никакой

Правило, к которому я пришёл на этой работе:

Если критерий приёмки нельзя проверить программой, это не критерий, а надежда.

Разберу на нашем же случае.

«База открывается» — не критерий. База прекрасно открывается в состоянии, когда тесты не запускаются: расширение не применено, обработчика нет, режим совместимости старый. Именно это и вводило в заблуждение дольше всего.

«Тесты зелёные» — не критерий. Кто смотрел, когда, на какой версии конфигурации, все ли тесты были в наборе? Утверждение не проверяемо задним числом.

«Файл junit.xml существует, exitCode = 0, число тестов совпадает с ожидаемым» — критерий. Проверяется программой, воспроизводится кем угодно, годится в CI без изменений.

Разница между вторым и третьим — не педантизм. Ровно из-за неё возник самый коварный случай во всей истории: тесты выполнялись, но отчёта не было. Прямые слэши в путях — YAxUnit не считал такой путь абсолютным и не писал файлы. Наблюдаемая картина — пустой каталог, то есть «прогон не стартовал». Реальность — прогон отработал полностью, что видно по данным, которые тесты создали в журнале регистрации.

Формулировка «тесты зелёные» здесь не помогла бы вообще: смотреть было не на что. Формулировка через файл и код возврата сразу указывает, где искать — между выполнением и записью результата.

Поэтому приёмка эталонов делалась так: слепок разворачивается в чистую базу, запускается прогон, проверяется наличие отчёта и код возврата. Не «выглядит рабочим», а предъявлен файл.


Проверка на сквозной задаче

Подход, не проверенный на реальной работе, остаётся презентацией. Полигоном стала первая из четырёх задач экзамена «1С:Специалист по платформе» — она достаточно велика, чтобы пройти всю линию целиком.

Постановка (в сокращении):

Компания собирает и продаёт компьютеры. Закупка деталей — «Приходная накладная», сборка системных блоков — «Сборка», продажа — «Расходная накладная». Учёт ведётся в разрезе подразделений, в каждом своя учётная политика: ФИФО, ЛИФО или по средней. Детали учитываются в разрезе характеристик через план видов характеристик. Нужны отчёты по остаткам и по продажам с прибылью.

Два решения, определившие остальное

Как совместить три метода списания в одном регистре. Регистр остатков ведёт измерение Партия — ссылку на документ поступления, заполняемую только на приход. Алгоритм выбирается по учётной политике подразделения:

  • по средней — берётся агрегированный остаток без разреза по партиям;
  • ФИФО/ЛИФО — читаются остатки в разрезе партий, партии перебираются по дате в прямом или обратном порядке.

Единая точка расчёта себестоимости для «Сборки» и «Расходной накладной». Это решение важнее первого. Дублирование логики между документами — типовая причина снижения оценки на экзамене, и в промышленной разработке ничем не лучше: расхождение между двумя копиями появляется на первой же правке.

Функция СписатьСебестоимость(Подразделение, Номенклатура, Характеристика, Количество, Дата) Экспорт

	// Измерение регистра типизировано ссылкой, поэтому Неопределено
	// передавать нельзя — ни в блокировку, ни в параметры запроса.
	Если Характеристика = Неопределено Тогда
		Характеристика = Справочники.ХарактеристикиНоменклатуры.ПустаяСсылка();
	КонецЕсли;

	СпособОценки = СпособОценкиПодразделения(Подразделение, Дата);

	// Управляемая блокировка на время чтения и использования остатка:
	// без неё два параллельных проведения спишут одну партию дважды.
	Блокировка = Новый БлокировкаДанных;
	ЭлементБлокировки = Блокировка.Добавить("РегистрНакопления.ОстаткиНоменклатуры");
	ЭлементБлокировки.УстановитьЗначение("Подразделение", Подразделение);
	ЭлементБлокировки.УстановитьЗначение("Номенклатура", Номенклатура);
	ЭлементБлокировки.УстановитьЗначение("Характеристика", Характеристика);
	Блокировка.Заблокировать();

	// ... чтение остатков и перебор партий

КонецФункции

 

Тесты

Шесть тестов: четыре на расчёт себестоимости и два сквозных сценария.

 

Тест Данные Ожидание
По средней партии 10×1000 и 10×1200, списываем 15 одна строка, сумма 1650
ФИФО те же партии 10×100 + 5×120 = 1600
ЛИФО те же партии 10×120 + 5×100 = 1700
Граничный случай запрос 15 при остатке 10 списывается ровно 10
Сборка 5 корпусов и 5 плат, собираем 2 блока детали 5→3, блоки по себестоимости 2000
Продажа 3 принтера по 10000, продажа за 42000 остаток в ноль, прибыль 12000

 

Граничный случай проверяет требование, за которое на экзамене снимают баллы: остаток должен выводиться в ноль одновременно по всем ресурсам регистра, и «в долг» списывать нельзя.

Результат прогона:

 

exitCode: 0
Всего: 6 | Успешно: 6 | С ошибками: 0

Результат прогона YAxUnit: два набора, 6 тестов из 6 успешно

 

Функциональный сценарий Vanessa Automation — 16 шагов через реальный интерфейс: открытие списков, создание элементов справочников через формы, проверка записи. Все шаги зелёные.


Аргумент, который стоит держать наготове

В спорах о целесообразности автотестов рано или поздно звучит: «зачем, у нас тестировщик всё проверяет руками». Вот фактический ответ из этой работы.

Тесты нашли в моём коде две ошибки.

Мин(). Такой функции во встроенном языке 1С нет — она есть только в языке запросов. Синтаксическая проверка /CheckModules её пропускает, ошибка вылезает только в рантайме.

Неопределено в типизированном измерении. Попытка передать его в управляемую блокировку даёт «Неверный тип значения» уже на Блокировка.Заблокировать().

 


Тест поймал ошибку: «Неверный тип значения» на вызове Заблокировать()

 

Обратите внимание на трассировку справа: показан не только текст ошибки, но и вся цепочка вызовов до строки в модуле. Поиск причины по такому отчёту занимает минуты.

А теперь главное. Обе ошибки прошли бы ручную приёмку — при условии, что проверяющий вводит данные с заполненной характеристикой. А он её заполнит: она в форме, поле на виду, сценарий выглядит естественно.

Ручная приёмка проверяет сценарий, который проверяющий придумал. Автотест проверяет тот, о котором не подумал никто.


Каталог молчаливых отказов

Всё перечисленное ниже ломает работу без внятной диагностики: либо вообще без сообщения, либо с сообщением, которое до вас не доходит.

 

Что вы видите Что на самом деле
Открылось обычное окно вместо прогона тестов В конфигурации нет ПриНачалеРаботыСистемы() — или у неё есть параметры
Тесты выполняются, но отчёта нет Прямые слэши в путях конфигурации запуска
Расширение «Активно = Да», но код не работает Расширение загружено, но не применено
Прогон висит, нет ни отчёта, ни лога Расширение подключено в безопасном режиме — сообщение осталось на экране
Маска в conf.cfg прописана, диалоги никуда не делись Значение — регулярное выражение, а не список: test1;test2;test3 не совпадёт ни с чем
В логе /Out вместо ошибки п»їРЎРёРЅ… Лог бывает UTF-16, UTF-8 с BOM и ANSI — разбор угадал не ту кодировку
«Пользователь ИБ не идентифицирован» В базе есть пользователи, значит /N обязателен на любой команде
«Ошибка исключительной блокировки» перед обновлением Базу держит открытый клиент или фоновое задание
«Нет права на запуск с требуемым режимом окна» Не хватает прав MainWindowMode*
«Запрещён запуск внешних обработок» Нет InteractiveOpenExtDataProcessors
Процесс запущен, окна нет, всё висит Запуск через cmd /c start без интерактивного рабочего стола
«Отсутствует файл базы данных 'Z:\1Cv8.1CD'» Путь с пробелами склеен в один аргумент
Мост перестал видеть все базы разом В JSON-конфиге появился BOM
Скрипт падает на «Unexpected token» в русских строках В .ps1 наоборот — BOM отсутствует

 

Каждая строка здесь — цена одного незафиксированного параметра окружения. Таблица нужна тем, кто ещё не зафиксировал состояние; после фиксации она перестаёт быть актуальной.

Разберу четыре самых коварных.

Сигнатура обработчика. ПриНачалеРаботыСистемы() — предопределённый обработчик события, и его сигнатура строго без параметров. Стоит написать ПриНачалеРаботыСистемы(Отказ, ПараметрыЗапуска) — и это уже обычная процедура: платформа её как обработчик не вызывает, механизм расширения не срабатывает, диагностики нет.

«Активно» ≠ «применено». /LoadCfg -Extension кладёт расширение в базу, но не подключает его. Нужен ещё /UpdateDBCfg -Extension. При этом список расширений показывает Активно = Да — и это вводит в заблуждение. Достоверная проверка — сравнить два источника:

РасширенияКонфигурации.Получить(Новый Структура, ИсточникРасширенийКонфигурации.БазаДанных)
РасширенияКонфигурации.Получить(Новый Структура, ИсточникРасширенийКонфигурации.СеансАктивные)

Есть в первом и нет во втором — не применено.

Дефолтный фильтр. При откате на настройки по умолчанию фильтр становится ["tests"] и совпадает по подстроке с именами вроде myproject_tests. Тесты запускаются, отчёт не пишется. Отсюда правило: «файла нет» не равно «тесты не запускались» — сначала проверьте журнал регистрации на предмет данных, которые создают сами тесты.

Маска, которая ничего не маскирует. Параметр DisableUnsafeActionProtection — это регулярное выражение, сопоставляемое со строкой соединения, а не перечень баз. Написанное по аналогии с другими настройками значение test1;test2;test3 ищет в строке соединения буквальную подстроку test1;test2;test3 и не находит её никогда. Ошибки не будет: параметр валиден, синтаксис корректен, диалоги продолжают вылезать. Надёжнее задавать маску по расположению — тогда она попадает во все базы каталога сразу и переживает их переименование. И не стоит писать .* без уточнения: это снимет защиту у всех баз установки, включая рабочие.


Где этот подход не работает

Границы применимости важнее списка достоинств: решение, у которого их нет, обычно просто плохо изучено.

 

Ситуация Что ломается Чем заменять
Типовая на десятки-сотни ГБ .dt нереален по времени выгрузки и объёму Постоянные слоты, скрипт развёртывания с докатом и реестр состояния (разбор ниже)
Команда работает через хранилище конфигурации Конфигурация в эталоне быстро расходится с хранилищем Фиксировать только окружение, конфигурацию брать из хранилища
В базе персональные данные Эталон с данными нельзя раздавать разработчикам Эталон только с настройками, данные — генератором
Обновление платформы Эталон привязан к версии, тихо устаревает Регламент пересборки и приёмки после каждого обновления
Правка одного метода в готовой конфигурации Вся линия — оверинжиниринг Здравый смысл

 

Что происходит на большой конфигурации

Первый случай самый частый, и его стоит разобрать на числах — тем более что я в него уже упёрся.

Для проверки совместимости расширения с разными типовыми и релизами понадобился пул из пяти постоянных слотов. Порядок величин там другой: одна демо-база — около 4,3 ГБ, её выгрузка в XML — около 8,5 ГБ и 42–49 минут. Причём выгрузка занимает почти всё время развёртывания слота: скачивание дистрибутива 3–10 минут, распаковка меньше семи, восстановление базы 2–4, установка расширения с тестами полторы минуты, прогон тестов полминуты — и сорок с лишним минут на выгрузку.

Замораживать такое слепком бессмысленно: .dt пришлось бы пересобирать на каждый релиз каждой конфигурации, а хранить — десятками гигабайт.

Поэтому носитель состояния меняется, а принцип — нет. Вместо одного слепка используются два артефакта в паре:

Скрипт развёртывания с докатом. Тот самый скрипт, который выше я называл недостаточным, — но с двумя обязательными свойствами. Он проходит все шаги за один вызов и умеет продолжаться с прерванного места, не повторяя скачивание и распаковку. Без доката сорокаминутная выгрузка превращает любой сбой на последнем шаге в потерю часа.

Реестр состояния. Обычный файл, где записано, что именно сейчас развёрнуто в каждом слоте, какого релиза, когда собрано и в каком состоянии проверки. Он объявлен единственным источником правды и обновляется при каждой пересборке.

Разница с чеклистом принципиальная: чеклист описывает, что нужно сделать, реестр — что фактически сделано. Первое устаревает молча, второе расходится с реальностью заметно, потому что рядом лежат результаты прогонов.

Принцип сохраняется: состояние фиксируется в артефакте, приёмка идёт по машинно-проверяемому критерию. Меняется носитель, не идея. Для одиночной базы это слепок, для пула больших конфигураций — скрипт с докатом плюс реестр.


Стоимость владения

Что придётся платить постоянно, а не однократно.

Пересборка эталонов при смене платформы. Не автоматическая: собрать, развернуть в чистую базу, прогнать тесты, убедиться в exitCode = 0. Полчаса-час на каждый эталон.

Рост репозитория. Слепки хранятся в LFS, каждая версия — это мегабайты, которые не сжимаются и не диффятся. Историю приходится чистить осознанно.

Ревизия состава. Появилось новое требование к окружению — эталон устарел, и узнаете вы об этом по упавшему прогону, а не по предупреждению. Состав эталона — такой же объект поддержки, как код.

Актуальность пула. Там, где вместо слепков живут постоянные слоты, платить приходится и местом, и временем: каждый новый релиз — это ещё несколько гигабайт и около часа развёртывания, из которых сорок с лишним минут занимает одна только выгрузка. Плюс дисциплина обновления реестра: слот, пересобранный без записи в реестр, хуже отсутствующего — на него будут ссылаться как на проверенный.

Дисциплина приёмки. Соблазн сказать «база вроде открылась, наверное всё хорошо» никуда не девается. Критерий работает, только пока его действительно проверяют.

Итог честный: это дешевле, чем семь ручных шагов на каждого нового человека, но не бесплатно. Если в команде один разработчик и окружение не меняется годами — выигрыш сомнителен.


Следующий шаг: разделить линию между исполнителями

Разделение возможно потому что есть контракты. Без артефактов на границах любое разделение ролей превращается в переписку и согласования.

Постановка
   ↓
[архитектор]   → JSON метаданных, архитектурные инварианты
   ↓
[исполнитель]  → метаданные, модули, формы, отчёты
   ↓
[тестировщик]  → тесты, прогон, junit.xml
   ↓
[ревьюер]      → находки, severity, вердикт

Ревьюер обязательно на другой модели. Модель, написавшая код, плохо видит собственные ошибки — ей нужен независимый взгляд, а не самопроверка. Ровно та же логика, по которой автор не ревьюит свой merge request.

Тестировщик отдельно оправдан тем, что прогон — длинная операция, засоряющая контекст логами платформы, которые остальным стадиям не нужны.

Но есть и обратная сторона.

Дробить ради дробления вредно. Каждый агент стартует «холодным» и заново выводит контекст. Для правки одного метода цепочка из четырёх агентов — чистые потери.

Разделение ролей не решает главную проблему. Больше всего времени в этой истории ушло не на объём работы, а на диагностику молчаливых отказов. Агент упёрся бы в них ровно так же и потратил бы столько же. Лечит это зафиксированное состояние, а не организационная схема.

Начинать стоит с двух ролей — исполнитель и ревьюер. Это даёт основную пользу при минимальной сложности.


Что дальше

CI/CD. Прогон тестов на каждый push. Всё для этого готово: junit.xml — стандартный формат, exitCode — машиночитаемый результат. Критерий приёмки, сформулированный правильно с самого начала, переносится в пайплайн без переделки.

Остальные задачи экзамена. Бухгалтерский учёт, периодические расчёты, бизнес-процессы — линия та же, меняется только предметная область.

Перенос на рабочие конфигурации уже состоялся — учебная задача была полигоном, а проверка совместимости расширения потребовала пула из пяти постоянных слотов с типовыми и их разными релизами. Тесты там зелёные на каждом слоте, и линия отработала ровно то, ради чего строилась: на одном из релизов проверка показала несовместимость, которую иначе выяснил бы клиент.

Что изменилось при переносе — только носитель состояния и его цена (см. раздел о границах). Контракты, критерий приёмки и каталог отказов не изменились вовсе.


Решения, которые можно забрать

Даже если у вас другой инструментарий:

  1. Фиксируйте состояние окружения в артефакте, а не в документации. Документация не проверяется автоматически и устаревает молча. Носитель выбирается по масштабу: для одиночной базы — слепок, для пула больших конфигураций — скрипт с докатом и реестр того, что фактически развёрнуто.
  2. Формулируйте критерий приёмки так, чтобы его проверяла программа. «Открывается» и «выглядит рабочим» не годятся. Годится «файл существует, код возврата ноль».
  3. Считайте молчаливые отказы отдельным классом угроз и закрывайте их системно. Внимательность — расходуемый ресурс, а не механизм контроля.
  4. Передавайте между стадиями файлы с контрактами, а не договорённости. Тогда стадию можно отдать кому угодно, а ошибку — локализовать.
  5. Называйте границы применимости своих решений вслух. Решение без известных границ не изучено, а просто пока не сломалось.

Таблица «симптом → причина» выше — прикладной бонус: она экономит часы на диагностике, пока состояние окружения ещё не зафиксировано.


Инструментарий собран с использованием набора навыков для AI-агентов и MCP-серверов для 1С. В статье приведены собственные наработки: эталонные базы, чеклист готовности, диагностика молчаливых отказов и решение учебной задачи. Буду рад вопросам и замечаниям в комментариях — особенно от тех, кто ловил похожие отказы и знает строки для таблицы, которых у меня нет.

Вступайте в нашу телеграмм-группу Инфостарт

YAxUnit Vanessa Automation автотесты тестирование юнит-тесты эталонная база воспроизводимость CI/CD пакетный режим конфигуратор 1С:Специалист аттестация оперативный учет DevOps junit

Вы можете заказать платную адаптацию этой статьи под ваши задачи на «Бирже заказов».

  • 0% комиссии — оплата напрямую исполнителю;
  • Исполнители любого масштаба — от отдельных специалистов до команд под проект;
  • Прямой обмен контактами между заказчиком и исполнителем;
  • Безопасная сделка — при необходимости;
  • Рейтинги, кейсы и прозрачная система откликов.

См. также

Тестирование QA Программист Бесплатно (free)

Разбираем, как в крупных компаниях регуляторные требования, постмортемы и внутренние ограничения постепенно превращаются в многоуровневую систему инструкций, в которой разработчику все сложнее понять, что и когда нужно проверить. Показываем opensource-сервис внешних проверок для GitLab, который автоматизирует часть этой бюрократии и сводит результат к понятному сигналу: зеленое – все в порядке, красное – нужно обратить внимание на конкретное требование. Объясняем, как такие проверки помогают «сдвинуть влево» контроль задач и снизить риск отказа во внедрении задачи в последний момент перед релизом. А заодно смотрим, может ли связка Autumn + «Вино» + немного разработческого энтузиазма превратить обязательные инструкции в инструмент, который команда сама захочет развивать.

12.08.2026    296    Golovanoff    1    

3

Поиск данных Тестирование QA Программист 1С 8.3 1С 8.5 Бесплатно (free)

Как мы пришли к Юнит-тестированию и почему стоит его использовать. Использование универсальных тестов для проверки работы IS MagicInput в вашей конфигурации.

16.07.2026    1803    Evg-Lylyk    2    

5

Тестирование QA Программист Бесплатно (free)

Tantor Postgres 18 - масштабный релиз СУБД, за которым стоят месяцы тестирования, сотни часов нагрузочных прогонов и десятки исправлений, о которых пользователь никогда не узнает просто потому, что они были найдены и устранены до выхода версии. Александр Симонов, руководитель направления развития 1С в "Тантор Лабс", рассказывает, как устроен процесс тестирования изнутри - почему одного эталонного прогона недостаточно, что делать, когда ванильный PostgreSQL 18 ломает собственные оптимизации, и как Tantor Postgres приближается к той планке, которую MS SQL Server держал годами.

07.07.2026    1266    Tantor    2    

6

Тестирование QA Программист Бесплатно (free)

Юнит-тестирование в 1С – тема, о которой много говорят, но внедряют далеко не везде: для одних это признак зрелой разработки, для других – избыточная формальность или лишняя трата времени. Разбираем, почему классическая пирамида тестирования в 1С часто оказывается перевернутой, какие ограничения накладывает платформа и почему юнит-тесты в реальных проектах нередко смешиваются с интеграционными. Показываем, где юнит-тесты действительно помогают ускорить разработку, упростить проверку логики и повысить качество кода, а где их применение превращается в хрупкую и дорогую поддержку. Отдельно разбираем типичные ошибки: зависимость тестов от данных и окружения, избыточное мокирование, тестирование платформы вместо бизнес-логики и отсутствие негативных кейсов.

29.06.2026    2850    alexandr_yang    6    

12

Тестирование QA Программист 1С:Предприятие 8 Бесплатно (free)

Как мы пришли к использованию Ванессы для автоматизации действий пользователей? Сначала я увидел в интернете лекцию Олега Филиппова про RPA. И когда встал вопрос про автоматизацию небольших процессов, то эта лекция у меня прекрасно соединилась с опытом тестирования программ с помощью Vanessa Automation. Минимум усилий, минимум ручного кода и высокая скорость внедрения. И самое главное, не надо менять программу. А если программа изменится, то алгоритм быстро поправить и дополнить.

19.06.2026    1992    swimdog    3    

8

Тестирование QA Программист Россия Бесплатно (free)

Разбираемся, какие виды тестирования нужно проводить при внедрении заказных бизнес-приложений. Что такое воронка «бесконечного тестирования». Чем синдром «сапера» отличается от синдрома «лудомана». А также можно ли полюбить тестирование.

18.06.2026    1430    DmitryShostak    0    

2

Тестирование QA Бесплатно (free)

Нагрузочное тестирование 1С нельзя строить на средних значениях и одном «идеальном» сценарии: такой подход скрывает пики, блокировки, фоновые задания и реальные риски для производительности. Показываем, как собрать данные из технологического журнала, журнала регистрации и поведения пользователей, чтобы построить сценарий, близкий к работе системы в продуктиве. Разбираемся, как вариация, корреляционный анализ и APDEX помогают увидеть неравномерную нагрузку, уточнить модель и понять, какие данные влияют на производительность. А также объясняем, как корректное моделирование помогает заранее выявить проблемы, подобрать железо под реальные пики и снизить риск коллапса системы после запуска.

12.05.2026    3153    gabrielyants    8    

13

Тестирование QA Программист Бесплатно (free)

Переход на Linux и PostgreSQL – серьезный этап для любой компании. Нагрузочное тестирование помогает пройти его без критических сбоев: заранее выявить узкие места, оценить поведение системы под реальной нагрузкой и снизить риск откатов после запуска. В статье разберем, почему миграция с Microsoft SQL Server и Windows на новую инфраструктуру требует отдельной проверки производительности, какие сценарии стоит включать в тест, как настраивать контур и мониторинг, как оценивать результаты и сколько времени реально занимает такой проект.

29.04.2026    2042    kulmaksim    0    

3
Для отправки сообщения требуется регистрация/авторизация