На одном из проектов была поставлена задача написать ряд тестов, перед оптимизацией бизнес-процесса. Одним из требований было использование VA, но оптимизация включала в себя некоторые интерфейсные доработки, и при тестировании интерактива суть теста терялась: писать достаточно сложные проверки, чтобы их потом переписывать... Возникла идея проверять серверную логику через обработку - действительно, каждый шаг скрипта представляет собой метод, а там уже можно реализовать проверку чего угодно. Но и здесь получалось как-то некошерно - во-первых с загрузкой тестовых данных через табличный документ (который надо версионировать), во-вторых с собственно проверкой объектов. Да, можно написать такой тест, но он был-бы замкнут на себе - куча кода в служебном разделе, и при необходимости нового подобного теста возникает естественное дублирование кода. Лечить такое можно только библиотекой, и я начал писать плагин с API, позволяющим проверять объекты конфигурации. Позже этот плагин превратился в довольно мощный механизм уже для программного создания, заполнения, и проверки объектов. Реализованный интерфейс позволяет описывать все это прямо в теле скрипта, и таким образом - решается проблема версионирования, а также проблема наглядности. И спустя еще некоторое время он был внедрен в VA, с разрешения заказчика и Леонида Паутова, за что им большое спасибо.
Ссылка на проект VA: https://github.com/Pr-Mex/vanessa-automation
Ссылка на вводную статью: Разработка и сценарное тестирование с Vanessa-ADD..
Прежде всего - что такое "ИнициаторДанных". Это управляемая форма в обработке VA, предоставляющая экспортные интерфейсы для работы с ссылками: создание, изменение и проверка объектов. Реализована очистка данных, созданных при работе сценария. Проработана поддержка платформы 8.2. Инициатор имеет собственный клиентский кэш, время жизни которого - запуск сценариев одной фичи. Это значит, что при работе сценария переменные живут в одном пространстве имен, и дублирование имени переменной вызовет ошибку. Для инициатора реализована библиотека шагов, которая находится по адресу: "..\vanessa-automation\features\Libraries\ИнициаторДанных\БиблиотекаШаговИнициаторДанных.feature". Можно открыть ее, а можно нажать на кнопку:
Для описания API был реализован демо-пример, фича доступна в поставке VA "..\vanessa-automation\examples\features\Demo_8_3\ИнициаторДанных\Демо инициатора.feature". Этот скрипт хорошо закомментирован, и я не вижу смысла заново описывать поведение в статье, оставлю его здесь:
# Как запустить сценарий:
# 1) Сформировать тестовые базы ("..\vanessa-automation\tools\1 PrepareCheck.cmd")
# 2) Прописать, и запустить ..vanessa-automation\tools\ServiceBases\v83ServiceBase83xx
# 3) Открыть Ванессу, загрузить фичу, выполнить.
Функционал: Проверка и демонстрация методов плагина ИнициаторДанных
Как Разработчик
Я Хочу:
- программно создавать ссылочные объекты при работе сценария
- использовать имена переменных, а также идентификаторы предопределенных данных в качестве указателей на ссылку, при написании сценария
- выполнять проверку заполненности реквизитов, движений, табличных частей, описывая эталон в теле скрипта
Сценарий: Подготовка окружения
Дано *Я создаю тестовые данные
И я нахожу или создаю ссылки
# Демонстрация создания группы справочника.
# Здесь два параметра. Первый - имя менеджера, второй - имя переменной, для помещения созданной (или найденной) ссылки.
И я нахожу или создаю группу объекта "Справочники.Контрагенты" с именем "ГруппаКонтрагентов"
# Демонстрация создания элемента справочника, по аналогии с созданием группы.
# Элементы создаются с автоматически генерируемым GUID, который привязан и уникален в разрезе:
# - имени фичи (текст тега "Функционал")
# - имени менеджера
# - имени переменной
И я нахожу или создаю объект "Справочники.Контрагенты" с именем "Контрагент"
#Демонстрация заполнения реквизитов ранее созданной ссылки по переданной таблице
И я заполняю реквизиты объекта "Контрагент" по таблице:
# При создании\проверке реквизитов всегда должна использоваться таблица с колонками "Имя, Значение"
|Имя |Значение |
# Демонстрация использования переменной "ГруппаКонтрагентов" как ссылки в теле скрипта
|Родитель |ГруппаКонтрагентов |
# Демонстрация функционала приведения идентификаторов предопределенных данных:
# здесь "ЮридическоеЛицо" - значение перечисления "ЮридическоеФизическоеЛицо", однако в таблице можно указывать
# идентификатор значения перечисления, либо ИмяПредопределенныхДанных.
|ЮрФизЛицо |ЮридическоеЛицо |
И я нахожу или создаю объект "Справочники.Организации" с именем "Организация"
И я нахожу или создаю объект "Справочники.Товары" с именем "Товар1"
И я устанавливаю константы
И я устанавливаю константу "ОрганизацияПоУмолчанию" в значение переменной "Организация"
Сценарий: Проведение поступления с контрагентом, не включенным в черный список
Дано Я создаю тестовые данные
# В одной фиче может быть несколько сценариев, при этом стоит стремиться какие-то основные вещи (Организации,
# Контрагенты, заполнение календаря, установка констант, etc) создавать в первом сценарии "ПодготовкаОкружения".
# В прочих же только контекст.
И я нахожу или создаю ссылки
# Демонстрация создания документа (объекта с поддержкой оси времени):
И я нахожу или создаю объект "Документы.ПоступлениеТоваров" с именем "ДокПТУ1" на дату 01.02.2020
И я заполняю реквизиты объекта "ДокПТУ1" по таблице:
|Имя |Значение |
|Поставщик |Контрагент |
И я заполняю табличную часть "Товары" объекта "ДокПТУ1" по таблице:
|Номенклатура |Количество |Сумма |
|Товар1 |10 |100 |
# Демонстрация проверки заполнения - если проверка заполнения не будет выполнена, инициатор выбросит исключение. Текст
# исключения собирается из сообщений пользователю события системы "ОбработкаПроверкиЗаполнения"
Когда я выполняю проверку заполнения объекта "ДокПТУ1"
# Демонстрация проведения - если проведение завершилось с ошибкой, инициатор выбросит исключение. Текст
# исключения собирается из сообщений пользователю события системы "ОбработкаПроведения", а также описанием самой ошибки.
Тогда я записываю документ "ДокПТУ1" в режиме "Проведение"
# Демонстрация функционала проверки перечня реквизитов по таблице геркина:
И я проверяю реквизиты объекта "ДокПТУ1" по таблице:
|Имя |Значение |
|Проведен |Истина |
|Организация|Организация|
# Демонстрация проверки заполнения субколлекции объекта - табличной части, или движений как в этом случае
И Я проверяю, что движения документа "ДокПТУ1" по регистру "Запасы" идентичны таблице:
|Номенклатура |Количество |Поставщик |
|Товар1 |10 |Контрагент |
Сценарий: Проведение поступления с контрагентом, включенным в черный список
Дано Я создаю тестовые данные
И я записываю документ "ДокПТУ1" в режиме "ОтменаПроведения"
# Демонстрация создания записей регистра сведений:
И я создаю записи регистра сведений "ЧерныйСписокКонтрагентов" по таблице:
|Период |Контрагент|Включен |
|01.01.2020 |Контрагент|Истина |
И я записываю документ "ДокПТУ1" в режиме "Проведение"
И я проверяю реквизиты объекта "ДокПТУ1" по таблице:
|Имя |Значение |
|Проведен |Ложь |
Сценарий: Проведение поступления с контрагентом, исключенным из черного списка
Дано Я создаю тестовые данные
И я записываю документ "ДокПТУ1" в режиме "ОтменаПроведения"
# Демонстрация создания записей регистра сведений:
И я создаю записи регистра сведений "ЧерныйСписокКонтрагентов" по таблице:
|Период |Контрагент|Включен |
|02.01.2020 |Контрагент|Ложь |
И я записываю документ "ДокПТУ1" в режиме "Проведение"
И я проверяю реквизиты объекта "ДокПТУ1" по таблице:
|Имя |Значение |
|Проведен |Истина |
Сценарий: очистка окружения
Дано Я откатываю изменения
В статье же рассмотрим некоторые нюансы..
Реализовано создание ссылочных объектов всех видов, а также шаги библиотеки:
- И я нахожу или создаю группу объекта "КлассМнч.Вид" с именем "ИмяПеременной"
- И я создаю записи регистра сведений "ИмяРегистра" по таблице:
|Период |ИмяИзмеренияN |ИмяРесурсаN |ИмяРеквизитаN |
- И я нахожу или создаю объект "КлассМнч.Вид" с именем "ИмяПеременной" на дату 30.08.2020
- И я нахожу или создаю объект "КлассМнч.Вид" с именем "ИмяПеременной"
Создание объекта, использующего ось времени (Документы, Задачи, БизнесПроцессы) вызовет ошибку при не-указании даты. При создании объекта GUID ссылки генерируется автоматически, ссылка сохраняется в кэше инициатора. Имя переменной, в которую помещается ссылка можно использовать далее в теле скрипта. При создании справочных записей автоматически генерируется наименование (см. метод "12. Формирование представления по идентификатору" в Универсальные функции с примерами использования).
В созданном объекте можно заполнять реквизиты и табличные части, используя таблицу геркина. При заполнении реквизитов на вход ожидаются колонки "Имя", "Значение":
И я заполняю реквизиты объекта "Контрагент" по таблице:
|Имя |Значение |
|Родитель |ГруппаКонтрагентов |
|ЮрФизЛицо |ЮридическоеЛицо |
Идентификаторы предопределенных данных в колонке "Значение" распознаются автоматически, за исключением реквизитов составного типа. При наличии реквизита составного типа требуется поместить ссылку в переменную, и обращаться к этой переменной:
И я нахожу или создаю объект "Справочники.Контрагенты" с именем "Плательщик"
И я нахожу или создаю объект "Документы.ПриходныйКассовыйОрдер" с именем "ПКО" на дату 30.08.2020
И я заполняю реквизиты объекта "ПКО" по таблице:
|Имя |Значение |
|Контрагент|Плательщик |
В шагах заполнения объектов также реализованы шаги для проведения документов. Вариантов проведения два: с вызовом исключения, и без. Это сделано для возможности проверки ситуации, когда документ не должен провестись. В этом случае проверка может выглядеть так:
# Проверка ошибки проведения:
И я записываю документ "ПКО" в режиме "Проведение"
И я проверяю реквизиты объекта "ПКО" по таблице:
|Имя |Значение |
|Проведен |Ложь |
# Для проверки успешного проведения можно использовать шаг, вызывающий исключение:
И я записываю документ "ПКО" в режиме "Проведение" с вызовом исключения
Реализованы проверки: заполнения объекта, сверка движений документа по таблице, сверка реквизитов объекта по таблице, сверка табличной части объекта по таблице. При проверке реквизитов таблица эталона описывается по тем-же правилам, что и при заполнении (см. заполнение объектов).
Реализованы методы, удаляющие переменные и связанные с ними ссылки из БД. Подробнее см. ниже "Структура сценариев фичи".
Такой порядок сценариев наиболее удобно на мой взгляд применять при работе с этим подходом:
- "Сценарий: Подготовка окружения" - здесь создаются объекты, общие для прочих сценариев всей фичи. Т.е. это такой служебный раздел - в нем инициализируются константы типа "ВалютаРеглУчета", создаются элементы организаций, некие второстепенные но нужные справочники - номенклатура, контрагенты, статьи учета.
- "Сценарий: <проверка поведения>" - здесь собственно проверяется нужное поведение, создаются уникальные для этого сценария сущности - например ввод остатков операцией по товару, а затем ввод списания со склада - если списание успешно проведено, то тест пройден. В конце каждого сценария проверки поведения рекомендуется использовать известный шаг: "я удаляю переменные текущего сценария". Этот метод освобождает имена переменных сценария, удаляет ссылки \ записи регистров сведений, и восстанавливает значения констант к тем, которые были установлены до начала сценария.
- "Сценарий: очистка окружения" - этот сценарий состоит из одного шага "Я откатываю изменения". Выполняются действия, описанные выше, но для всей фичи.
В предыдущих версиях API уникальный идентификатор ссылки поставлялся обработчиком фичи. Это соответственно приводило к необходимости его создавать)) Я думаю, минусы хранения лишней обработки очевидны. Был реализован такой алгоритм: в шаге "я нахожу или создаю ссылку с именем" инициатор берет имя фичи, имя менеджера объекта, и имя переменной. Переводит в уникальное 16-ричное число, и превращает его в ГУИД - первые блоки заполняются символами получившегося числа, оставшиеся добиваются нулями. Здесь у читателя должно сложиться понимание поведения: разрабатываем тест, и понадобилось изменить имя фичи. Это значит что если в базе на которой проверяется тест уже были прогоны, ссылки задублируются. Т.е. ГУИД генерируется в разрезе фичи, имени менеджера, имени переменной.
Ну, вот кажется и все. Спасибо за внимание, буду рад идеям, предложениям, критике.