Как программно выполнить команду управляемой формы и отменить транзакцию записи для автотеста

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке автотестов в среде 1С программисты часто сталкиваются с дилеммой: необходимо проверить работу логики, заложенной в управляемую форму (УФ), выполнить проведение документа, убедиться в корректности созданных движений, но при этом не допустить изменения данных в информационной базе. Основная сложность заключается в том, что управляемая форма работает на стороне клиента, а транзакция записи и проведения документа выполняется на стороне сервера. Разберем подробно, как объединить эти процессы и реализовать полноценный тест с откатом изменений.

Проблема разделения контекстов: Клиент и Сервер

Рассмотрим ситуацию, описанную в теме. Автор хочет получить форму, нажать на ней кнопку (выполнить команду), провести документ и отменить транзакцию. В 1С невозможно просто обернуть вызов ОткрытьФорму() в конструкцию НачатьТранзакцию() и ОтменитьТранзакцию(). Это связано с тем, что транзакция базы данных — это серверный процесс, жестко привязанный к конкретному сеансу и вызову, в то время как форма живет своей «клиентской жизнью».

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

Метод реализации: Использование флага Отказ

Наиболее эффективным решением для автотеста является имитация «ошибки» в самом конце процесса записи. Если в процедурах ПриЗаписи или ОбработкаПроведения установить параметр Отказ = Истина, платформа 1С автоматически откатит всю транзакцию, включая все движения по регистрам и изменения в связанных объектах.

Для реализации этого механизма нам потребуется выполнить следующие шаги:

  1. Передать в форму или объект признак того, что текущая операция является тестовой.
  2. Выполнить команду формы (например, программно нажав кнопку).
  3. В серверном событии перехватить этот признак, выполнить проверку данных и вызвать отмену.

Выясним, как передать маркер теста. Поскольку транзакция записи документа может включать в себя множество подписок на события, нам нужно, чтобы наш «флаг» прошел через всю цепочку. Рассмотрим использование ДополнительныеСвойства объекта.

Шаг 1: Программный вызов команды формы

Если мы работаем в обычном режиме (не через Тест-клиент), вызвать команду формы напрямую бывает сложно, так как процедуры команд обычно не являются экспортными. Проанализируем два пути решения:

Вариант А: Рефакторинг. Выносим логику команды в экспортный метод модуля объекта или общего модуля. Это наиболее правильный путь с точки зрения архитектуры. В этом случае тест будет вызывать не форму, а конкретный метод.

Вариант Б: Использование расширения. Если конфигурация типовая и менять ее нельзя, можно создать расширение, которое сделает обработчик команды формы экспортным или добавит тестовую кнопку.

Вариант В: Интерфейс автоматизированного тестирования. Это штатный механизм платформы. При запуске 1С с ключом /TestClient, мы можем подключиться к нему через /TestManager и использовать объект ТестируемоеПриложение. Рассмотрим пример вызова команды:


// Код в Тест-менеджере
Окно = ТестируемоеПриложение.НайтиОбъект(Тип("ТестируемоеОкноКлиентскогоПриложения"), "НазваниеДокумента");
Форма = Окно.НайтиОбъект(Тип("ТестируемаяФорма"));
Форма.ВыполнитьКоманду("ЗаписатьИПровести");

Шаг 2: Перехват в модуле формы или объекта

Чтобы отменить транзакцию, нам нужно вставить код в событие ПриЗаписи на сервере. Важно понимать, что событие ПриЗаписи в модуле управляемой формы все еще находится внутри транзакции. Как подтверждено в сообщении 26, это «последнее звено» перед окончательной фиксацией данных.

Рассмотрим пример кода в модуле формы, который позволит нам «протестировать» запись и откатить ее:


&НаСервере
Процедура ПриЗаписиНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
    
    // Проверяем, пришел ли параметр, указывающий на автотест
    Если Параметры.Свойство("ЭтоАвтотест") И Параметры.ЭтоАвтотест Тогда
        
        // Здесь мы можем выполнить проверку движений, которые сформировал документ
        // Они уже находятся в коллекции ТекущийОбъект.Движения, 
        // но еще не зафиксированы в таблицах БД окончательно.
        
        Для Каждого НаборЗаписей Из ТекущийОбъект.Движения Цикл
            НаборЗаписей.Прочитать(); // Читаем то, что подготовил механизм проведения
            Если НаборЗаписей.Количество() = 0 Тогда
                Сообщить("Ошибка: Движения не сформированы!");
            КонецЕсли;
        КонецЦикла;

        // Главный момент: отменяем транзакцию
        Отказ = Истина;
        Сообщить("Тест завершен успешно, изменения откачены.");
        
    КонецЕсли;
    
КонецПроцедуры

Шаг 3: Проверка движений и результатов

Одной из главных проблем, озвученных в дискуссии (сообщение 15), является проверка корректности движений по регистрам. Если мы просто установим Отказ = Истина, транзакция схлопнется, и мы не сможем посмотреть в базу, чтобы проверить результат.

Проанализируем ситуацию: внутри процедуры ОбработкаПроведения наборы записей уже заполнены. Мы должны выполнить все проверки ДО того, как установим Отказ = Истина.

Посмотрим на пример в модуле объекта:


Процедура ОбработкаПроведения(Отказ, РежимПроведения)
    
    // Основная логика проведения конфигурации
    // ... (стандартный код)
    
    // Вставка для автотеста
    Если ДополнительныеСвойства.Свойство("РежимАвтотеста") Тогда
        
        // Проверяем результат проведения
        Запрос = Новый Запрос;
        Запрос.Текст = "ВЫБРАТЬ * ИЗ РегистрНакопления.Продажи ГДЕ Регистратор = &Ссылка";
        Запрос.УстановитьПараметр("Ссылка", ЭтотОбъект.Ссылка);
        
        // ВАЖНО: В транзакции мы можем читать данные, которые еще не зафиксированы
        Результат = Запрос.Выполнить();
        
        Если Результат.Пустой() Тогда
            // Фиксируем ошибку во внешнем источнике (например, в лог-файл)
            ЗаписатьРезультатТестаВФайл("Ошибка: Нет записей в регистре Продажи");
        Иначе
            ЗаписатьРезультатТестаВФайл("Успех: Движения созданы");
        КонецЕсли;
        
        // Отменяем проведение, чтобы не загрязнять базу
        Отказ = Истина;
        
    КонецЕсли;
    
КонецПроцедуры

Использование специализированных инструментов

Для тех, кто хочет избежать «грязного» кода внутри рабочих модулей конфигурации, рекомендуется использовать фреймворки автоматизации, такие как Vanessa Automation. Эти инструменты работают по следующему принципу:

Рассмотрим подробнее преимущество удаления объекта вместо отката транзакции (как предлагалось в сообщении 22). Если ваша логика проведения очень сложная и включает в себя вызовы веб-сервисов или запись в файлы, то Отказ = Истина откатит только базу данных, но не внешние действия. В таких случаях лучше позволить транзакции завершиться, а затем программно удалить объект и его движения через Удалить() или пометку на удаление с последующей очисткой.

Выводы и рекомендации

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

1. Изоляция: Чтобы тест не мешал реальным пользователям, всегда проверяйте наличие специального признака (маркера теста) перед тем, как вызывать принудительный Отказ.

2. Точка отката: Используйте процедуру ПриЗаписиНаСервере в модуле формы, если вам нужно протестировать логику именно формы, или подписку на событие ОбработкаПроведения, если тестируется бизнес-логика объекта.

3. Сохранение логов: Помните, что при Отказ = Истина все записи в справочники и регистры сведений внутри 1С также будут отменены. Если вам нужно сохранить результат выполнения теста, записывайте его во внешние файлы или используйте ЗаписьЖурналаРегистрации (она выполняется вне основной транзакции в некоторых версиях платформы).

4. Проверка данных: Всегда выполняйте чтение наборов записей Движения или запросы к БД до момента установки флага Отказ.

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

← На главную