Перейти к основному содержимому

Тестовые данные

Тестовые данные, на мой взгляд, одна из самых сложных тем в тестировании решений на базе 1С:Предприятия.

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

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

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

Подходы к работе с данными

  1. Ручное наполнение тестовой базы (мы предварительно создаем все что необходимо для тестов в базе, а потом используем её для прогона тестов)
  2. Использование файлов с данными (макеты - сгенерированные в нужном формате файлы с описанием тестовых данных, загружаемые при выполнении тестов)
  3. Программное создание нужных данных внутри теста

У каждого из вариантов есть свои плюсы и минусы и при грамотной компоновке можно достичь наилучшего результата.

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

Если грамотно распределить тестовые данные на способы создания, можно добиться оптимального результата. Например, статичные данные создать вручную, сложные кейсы данных засунуть в макеты, а для программного создания реализовать методы-конструкторы, которые будем переиспользовать. Таким образом, сможем уйти от минусов того или иного подхода или минимизировать их вред.

Ниже хочу рассказать как мы работает с данными.

Образ тестовой базы

Для прогона тестов используется предварительно подготовленный образ базы, на котором гоняются тесты как в CI, так и на базах разработки.

Образ базы - это выгрузка (файл dt) или сама база (файл 1cd), на основании которого копированием или загрузкой создается база для прогона тестов.

Ручное наполнение тестовой базы

Образ предварительно настраивается вручную (либо методами обновления/миграции), вводится минимально необходимая информация и базовые настройки.

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

Программное создание данных

Все остальные данные тесты готовят для себя сами.

В большинстве случаев используется программное создание данных

  • Данные создаются кодом, используя механизмы движка
  • Используется генерация случайных значений, где это не противоречит требования
  • Тесты стараются прибрать за собой, используя транзакции или механизм удаления данных
  • Созданы отдельные модули-помощники реализующие типовые кейсы данных

Благодаря программной генерации данных вы получаете

  • Старый добрый код 1С, который понятен и не требует изучения дополнительных материалов
  • Переиспользование и кастомизация алгоритмов генерации данных - общие модули, экспортные методы, параметры.
  • Возможность создавать новые уникальные данные
  • Можете использовать уже готовую логику тестируемого решения
Общий модуль ТестовыеДанные
Функция НовыйТовар() Экспорт
// Логика генерации
КонецФункции

Функция НовыйПоставщик() Экспорт
// Логика генерации
КонецФункции

Функция НовоеПоступлениеТовара(Склад, Знач Товар = Неопределено, Знач Поставщик = Неопределено) Экспорт

Если Поставщик = Неопределено Тогда
Поставщик = НовыйПоставщик();
КонецЕсли;

Если Товар = Неопределено тогда
Товар = НовыйТовар();
КонецЕсли;

Возврат ЮТест.Данные().КонструкторОбъекта(Документы.ПоступлениеТоваров)
.Установить("Склад", Склад)
.Установить("Поставщик", Поставщик)
.ФикцияОбязательныхПолей();
.ТабличнаяЧасть("Товары")
.ДобавитьСтроку()
.Установить("Номенклатура", Товар)
.Фикция("Количество")
.Фикция("Цена")
.Провести();

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

Использование генерации случайных значений позволяет

  • Сократить количество кода

  • Акцентировать внимание на "важных" значениях Например, в тесте ниже важно, чтобы товар и склад в документах совпадали, дата расхода должна быть больше прихода, количество расхода меньше прихода.

    Тест
    Склад = ТестовыеДанные.НовыйСклад();
    Товар = ТестовыеДанные.НовыйТовар();

    ДатаПоступления = ЮТест.Данные().СлучайнаяДата();
    ДатаРасхода = ЮТест.Данные().СлучайнаяДатаПосле(ДатаПоступления);

    КоличествоРасход = ЮТест.Данные().СлучайноеПоложительноеЧисло(100);
    КоличествоПоступления = КоличествоРасход + ЮТест.Данные().СлучайноеПоложительноеЧисло(100);

    ТестовыеДанные.НовоеПоступлениеТовара(Склад, Товар, КоличествоПоступления, ДатаПоступления);
    ТестовыеДанные.НовыйРасходТовара(Склад, Товар, КоличествоРасход, ДатаРасхода);

    // Проверки
  • Вскрыть неожиданные проблемы, за счет случайности данных вы покрываете больше кейсов. Правда это имеет и негативный эффект - тесты могут "фонить", то падать, то успешно проходить, а также сложнее воспроизвести упавший тест.

Правильно организовав работу с тестовыми данными вы существенно облегчите процесс создания и поддержки тестов

  • Регламентируйте подход к именованию модулей и методов, это облегчит их поиск
  • Договоритесь как вы будете создавать общие модули, как разделяются по ним конструкторы, например:
    • Использовать один модуль на все методы-конструкторы, подходит для небольших решений.
    • Создаете модули по подсистемам (разрезы учета/функциональности) - для небольших и средних конфигураций.
    • Для каждого объекта/функциональности создается свой модуль с конструкторами - для больших и сложных проектов.
  • Выполняйте перекрестные ревью, делитесь знаниями в команде.