Главная » Хабрахабр » Все ругают самописные тестовые фреймворки. А мы своим довольны

Все ругают самописные тестовые фреймворки. А мы своим довольны

«Фактор» — чертовски сложный алгоритмический enterprise, он обрабатывает данные в промышленных масштабах. Меня зовут Елена Расторгуева, я отвечаю за продукт «Фактор» в HFLabs.

В статье я расскажу, как мы начинали тестировать «Фактор», как развивали автотесты и почему пришли к самописным фреймворкам.

Что за продукт такой — «Фактор»

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


Адреса́ пишут сотнями способов, поэтому под капотом у «Фактора» неслабый алгоритмический аппарат

«Фактор» работает как сервис: данные на вход — данные на выход.

Stateless сильно упрощает жизнь тестировщика. Это stateless-система, где каждое обращение не зависит от предыдущих. Намного сложнее тестировать stateful системы, когда важна последовательность действий.

За ошибки мы отвечаем головой вплоть до того, что отсутствие ошибок — часть SLA в договоре с заказчиком. Продукт должен быть надежным как МКС, потому что им пользуются банки, сотовые операторы, страховые, ритейлеры уровня «Ленты».

Один из критериев готовности задачи — «Добавлены автотесты». Из-за требований к надежности автотесты мы писали с самого начала разработки.

Начинали с ручной проверки и автотестов

Мы зарелизили «Фактор» в 2005 году и сначала тестировали его руками. Утром тестировщик прогонял автотесты на файле с кейсами и сравнивал результат обработки данных с результатом предыдущего дня: что изменилось после вчерашнего коммита кода.

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

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


Юнит-тест на проверку формата СНИЛС

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

Создали свой фреймворк

В традиционных юнит-тестах данные и код идут вперемешку, выискивать нужные участки тяжело.

DDT — это когда данные для тестирования хранятся отдельно от кода для тестирования. Поэтому мы попробовали автотесты в парадигме Data Driven Testing (DDT).

DDT стал прорывом: апдейтить кейсы в «эксельнике» невыразимо проще. Кейсы загружали из excel-файла, они лежали в колонках «Неочищенные данные» и «Ожидаемый результат».

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


От excel-файлов как хранилища мы отказались: текстовые быстрее открываются, не меняют содержимое, из них проще забрать данные

Фреймворку помогают стандартные инструменты:

  • TeamCity автоматически запускает тесты каждую ночь;
  • testNG сравнивает ожидаемый и фактический результаты.


Если результат отличается от ожидаемого, в TeamCity тест краснеет. Если всё как надо, тест зеленый

Доработали фреймворк под себя

С тех пор прошло 12 лет. За это время фреймворк оброс возможностями, которых нет в стандартных решениях.

Учет статуса задач в Jira. HFLabs придерживается Test Driven Development: сначала пишем тест или добавляем тест-кейсы на новое поведение, а только потом меняем функциональность.

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

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

Теперь все работает так: Поэтому мы добавили к отключенным кейсам номер таска и навернули немного автоматики.

  • тест-кейс отключают, сопоставив ему открытую задачу в Jira;


    Чтобы привязать кейс к задаче, пишем перед ним # и номер таска

  • фреймворк прогоняет тесты даже по отключенным кейсам. Но игнорирует падения, пока задача открыта в Jira;
  • как только задачу закрывают, тест начинает падать на привязанных к ней кейсах. Это сигнал: задачу сдали, а кейсы включить забыли;
  • если вдруг тест по отключенному кейсу начал проходить при открытой задаче, фреймворк об этом тоже сообщит. Возможно, пора включить кейс или закрыть привязанный к нему таск (плюс обновить release notes и сообщить заказчикам).

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

    Фреймворк говорит, что отключенный кейс проходит.

Так мы сохранили TDD и победили забывчивость при управлении тест-кейсами.


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

Но для нас это не всегда так. Актуализация тест-кейсов в полуавтоматическом режиме. Казалось бы, если тест падает, ищи ошибку в коде. Бывает, актуализировать нужно именно тест-кейсы, потому что изменились требования к результату.

Москва» одним полем. Например, раньше заказчик в очищенном адресе хотел «г. Пора менять тест-кейсы. Теперь он изменил архитектуру БД, хочет «город» одним полем, «Москва» — другим.

Раньше мы копировали эту разницу и руками обновляли тест-кейсы. Для упавшего теста TeamCity показывает разницу между ожидаемым и актуальным результатами. Для массовых изменений — очень затратное мероприятие.

Новый эталон можно взять из фактического результата, но это долго
Живой пример: мы научили «Фактор» определять страну по номеру телефона, тесты в TeamCity упали.

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

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

С новым эталоном тестировщик актуализирует кейсы в три шага.

  1. Скачивает сгенерированный файл.
  2. Проверяет через любой инструмент мерджинга, какие изменения попали в новый эталон. Оставляет только нужные.
  3. Коммитит.


Тестировщик проверяет, насколько обновления в новом эталоне корректны, и коммитит их

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

В одном только адресе куча составляющих: индекс, регион, типа регион, тип города, город, тип улицы, дом, строение, корпус, квартира. Стабилизация тестовых данных заглушками. «Фактор» возвращает обработанные данные в десятках полей. Так из одной строки на входе получаются десятки значений. К ним «Фактор» цепляет ИФНС, ОКАТО, ОКТМО и еще по мелочи.

Например, распознавание того же адреса прямо зависит от государственного справочника — ФИАС. Не все поля из результата нужно проверять тест-кейсами. Обновление каких-нибудь КЛАДР-кодов для домов роняло сотни тест-кейсов. А в нем регулярно меняются поля, для наших задач совсем посторонние.

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

Когда поле должно быть заполнено, но само значение не важно: $$NE$$. Когда поле вообще не нужно проверять, тестировщик пишет в ожидаемый результат условное обозначение: $$DNV$$.

Если поле не заполнено, что-то не так.
ФИАС ID в адресе есть всегда, поэтому мы проверяем его на всех тестах. А вот индекса может и не быть, поэтому при проверке ФИАС ID индекс мы игнорируем

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

Самописный фреймворк удобнее

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

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

Сейчас ищем java-разработчика, зарплата от 135 000 ₽ без вычета НДФЛ. Если нравится делать сложные штуки в энтерпрайзе, приходите к нам.


Оставить комментарий

Ваш email нигде не будет показан
Обязательные для заполнения поля помечены *

*

x

Ещё Hi-Tech Интересное!

[Перевод] Конфигурируйте Visual Studio в вашей организации с помощью .vsconfig

В Visual Studio 2017 Update 15.9 мы добавили возможность экспорта и импорта рабочей нагрузки и выбора компонентов в файл конфигурации установки Visual Studio. Разработчики могут импортировать эти файлы в новые или существующие установки. Проверка этих файлов в ваших исходных репозиториях ...

Тест-драйв nanoCAD СПДС Стройплощадка 8. Часть 1

Тест-драйв nanoCAD СПДС Стройплощадка 8 Мы начинаем публикацию тест-драйва по nanoCAD СПДС Стройплощадка. В первой части тест-драйва мы разберем работу со специальным инструментом Менеджер проектов, его основные функции и способы построения элементов стройгенплана. Во второй части тест-драйва мы рассмотрим построение ...