При разработке автотестов в среде 1С программисты часто сталкиваются с дилеммой: необходимо проверить работу логики, заложенной в управляемую форму (УФ), выполнить проведение документа, убедиться в корректности созданных движений, но при этом не допустить изменения данных в информационной базе. Основная сложность заключается в том, что управляемая форма работает на стороне клиента, а транзакция записи и проведения документа выполняется на стороне сервера. Разберем подробно, как объединить эти процессы и реализовать полноценный тест с откатом изменений.
Рассмотрим ситуацию, описанную в теме. Автор хочет получить форму, нажать на ней кнопку (выполнить команду), провести документ и отменить транзакцию. В 1С невозможно просто обернуть вызов ОткрытьФорму() в конструкцию НачатьТранзакцию() и ОтменитьТранзакцию(). Это связано с тем, что транзакция базы данных — это серверный процесс, жестко привязанный к конкретному сеансу и вызову, в то время как форма живет своей «клиентской жизнью».
Проанализируем технические ограничения: команда формы может вызывать серверные методы, открывать другие окна или запрашивать данные у пользователя. Единственный надежный способ прервать цепочку изменений, инициированную формой, — это вмешаться в сам процесс записи объекта на сервере.
Наиболее эффективным решением для автотеста является имитация «ошибки» в самом конце процесса записи. Если в процедурах ПриЗаписи или ОбработкаПроведения установить параметр Отказ = Истина, платформа 1С автоматически откатит всю транзакцию, включая все движения по регистрам и изменения в связанных объектах.
Для реализации этого механизма нам потребуется выполнить следующие шаги:
Выясним, как передать маркер теста. Поскольку транзакция записи документа может включать в себя множество подписок на события, нам нужно, чтобы наш «флаг» прошел через всю цепочку. Рассмотрим использование ДополнительныеСвойства объекта.
Если мы работаем в обычном режиме (не через Тест-клиент), вызвать команду формы напрямую бывает сложно, так как процедуры команд обычно не являются экспортными. Проанализируем два пути решения:
Вариант А: Рефакторинг. Выносим логику команды в экспортный метод модуля объекта или общего модуля. Это наиболее правильный путь с точки зрения архитектуры. В этом случае тест будет вызывать не форму, а конкретный метод.
Вариант Б: Использование расширения. Если конфигурация типовая и менять ее нельзя, можно создать расширение, которое сделает обработчик команды формы экспортным или добавит тестовую кнопку.
Вариант В: Интерфейс автоматизированного тестирования. Это штатный механизм платформы. При запуске 1С с ключом /TestClient, мы можем подключиться к нему через /TestManager и использовать объект ТестируемоеПриложение. Рассмотрим пример вызова команды:
// Код в Тест-менеджере
Окно = ТестируемоеПриложение.НайтиОбъект(Тип("ТестируемоеОкноКлиентскогоПриложения"), "НазваниеДокумента");
Форма = Окно.НайтиОбъект(Тип("ТестируемаяФорма"));
Форма.ВыполнитьКоманду("ЗаписатьИПровести");
Чтобы отменить транзакцию, нам нужно вставить код в событие ПриЗаписи на сервере. Важно понимать, что событие ПриЗаписи в модуле управляемой формы все еще находится внутри транзакции. Как подтверждено в сообщении 26, это «последнее звено» перед окончательной фиксацией данных.
Рассмотрим пример кода в модуле формы, который позволит нам «протестировать» запись и откатить ее:
&НаСервере
Процедура ПриЗаписиНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
// Проверяем, пришел ли параметр, указывающий на автотест
Если Параметры.Свойство("ЭтоАвтотест") И Параметры.ЭтоАвтотест Тогда
// Здесь мы можем выполнить проверку движений, которые сформировал документ
// Они уже находятся в коллекции ТекущийОбъект.Движения,
// но еще не зафиксированы в таблицах БД окончательно.
Для Каждого НаборЗаписей Из ТекущийОбъект.Движения Цикл
НаборЗаписей.Прочитать(); // Читаем то, что подготовил механизм проведения
Если НаборЗаписей.Количество() = 0 Тогда
Сообщить("Ошибка: Движения не сформированы!");
КонецЕсли;
КонецЦикла;
// Главный момент: отменяем транзакцию
Отказ = Истина;
Сообщить("Тест завершен успешно, изменения откачены.");
КонецЕсли;
КонецПроцедуры
Одной из главных проблем, озвученных в дискуссии (сообщение 15), является проверка корректности движений по регистрам. Если мы просто установим Отказ = Истина, транзакция схлопнется, и мы не сможем посмотреть в базу, чтобы проверить результат.
Проанализируем ситуацию: внутри процедуры ОбработкаПроведения наборы записей уже заполнены. Мы должны выполнить все проверки ДО того, как установим Отказ = Истина.
Посмотрим на пример в модуле объекта:
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
// Основная логика проведения конфигурации
// ... (стандартный код)
// Вставка для автотеста
Если ДополнительныеСвойства.Свойство("РежимАвтотеста") Тогда
// Проверяем результат проведения
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ * ИЗ РегистрНакопления.Продажи ГДЕ Регистратор = &Ссылка";
Запрос.УстановитьПараметр("Ссылка", ЭтотОбъект.Ссылка);
// ВАЖНО: В транзакции мы можем читать данные, которые еще не зафиксированы
Результат = Запрос.Выполнить();
Если Результат.Пустой() Тогда
// Фиксируем ошибку во внешнем источнике (например, в лог-файл)
ЗаписатьРезультатТестаВФайл("Ошибка: Нет записей в регистре Продажи");
Иначе
ЗаписатьРезультатТестаВФайл("Успех: Движения созданы");
КонецЕсли;
// Отменяем проведение, чтобы не загрязнять базу
Отказ = Истина;
КонецЕсли;
КонецПроцедуры
Для тех, кто хочет избежать «грязного» кода внутри рабочих модулей конфигурации, рекомендуется использовать фреймворки автоматизации, такие как Vanessa Automation. Эти инструменты работают по следующему принципу:
/TestClient.Рассмотрим подробнее преимущество удаления объекта вместо отката транзакции (как предлагалось в сообщении 22). Если ваша логика проведения очень сложная и включает в себя вызовы веб-сервисов или запись в файлы, то Отказ = Истина откатит только базу данных, но не внешние действия. В таких случаях лучше позволить транзакции завершиться, а затем программно удалить объект и его движения через Удалить() или пометку на удаление с последующей очисткой.
Подводя итог, можно выделить основную стратегию реализации автотеста с откатом для управляемых форм:
1. Изоляция: Чтобы тест не мешал реальным пользователям, всегда проверяйте наличие специального признака (маркера теста) перед тем, как вызывать принудительный Отказ.
2. Точка отката: Используйте процедуру ПриЗаписиНаСервере в модуле формы, если вам нужно протестировать логику именно формы, или подписку на событие ОбработкаПроведения, если тестируется бизнес-логика объекта.
3. Сохранение логов: Помните, что при Отказ = Истина все записи в справочники и регистры сведений внутри 1С также будут отменены. Если вам нужно сохранить результат выполнения теста, записывайте его во внешние файлы или используйте ЗаписьЖурналаРегистрации (она выполняется вне основной транзакции в некоторых версиях платформы).
4. Проверка данных: Всегда выполняйте чтение наборов записей Движения или запросы к БД до момента установки флага Отказ.
Следуя этим шагам, мы сможем эффективно имитировать работу пользователя в управляемом интерфейсе, полностью проверяя алгоритмы проведения документов без физического изменения данных в рабочей базе.