История о том, как можно делать автотесты без автотестеров (ну почти).
Дано:
Проект с небольшим бюджетом
Максимальное возможное количество тестировщиков на проекте = 2
Тим лид или автоматизатор, у которого есть еще несколько других проектов. Т.е. постоянно писать и обслуживать тесты не может
Найти:
Регрессионное тестирование за минимальное время
Потратить на это минимальное количество денег/времени/сил
По причине невысокого бюджета приходим к тому, что нет возможности нанять полноценных автотестировщиков
Тестирование без автотестов? А кто-нибудь может без них, если уже попробовал хотя бы раз?)
Пусть разработчики пишут автотесты? В целом да, но проект небольшой, разработчиков тоже немного и времени на тесты у разработчиков нет (Пилим фичи и правим баги, какие тесты)
Поиск решения:
Первое, что я начал искать - инструменты, которые записывают действия пользователя в автотест. Перепробовав несколько из них (Selenium IDE и др), я не смог ответить на вопросы: Вернувшись к тесту через полгода, ручной тестировщик сможет повторить его руками? Понятно, что происходит в тесте без запуска?
Учим тестировщиков автоматизации? Да, адекватный вариант решения, но он подходит далеко не всем. Во-первых время, это долго. Проект уже убежит вперед, нагонять поезд будет очень сложно. Во-вторых не все тестировщики готовы и могут обучиться полноценной работе с кодом
Отдаем на аутсорс автотесты? Отличный вариант, но дорого и нужно все равно сажать человека в проект. Т.к. он (проект) постоянно меняется, и поддерживать и расширять автотесты необходимо постоянно
А что, если посмотреть в сторону BDD/TDD фреймворков, под капотом переиспользовать современный playwright/cypress и использовать его в качестве автотестов? Почему нет? Тысячу раз да)
К чему пришли:
-
Разработали "универсальный" набор шагов и проверок для фронтовых действий пользователя. Универсальный набор шагов предполагает, что селекторы будут указаны прямо в тексте шага (да, я в курсе, что это плохо). В каждом шаге, где используется селекторы, присутствует обязательная переменная name. Она не используется непосредственно в действиях и нужна только для отчета и общего понимания теста без запуска, в ней можно писать любой текст, который сделает шаг теста более понятным. Например:
When Я нажимаю "Кнопку сохранить"/"[data-test-id="btn-save"]" Then Вижу в "Предупреждении для Email"/".email._error" текст ~ "Не может быть пустым" Then НЕ Вижу "Заявка успешно отправлена"/".request-complete._open"
Разработали и подготовили набор предусловий для создания сущностей через API (авторизация и очистка данных тоже через API)
ЗаставилиПопросили разработчиков добавить атрибут data-test-id каждому элементу интерфейса, с которым можно взаимодействовать (что такое атрибут data-test-id не описано в статье, но легко гуглится. Пример статьи Ссылка)Написали пару тестов для примеров тестировщикам
Показали тестировщикам, как работать с git и pull request (можно и без этого, но так удобнее)
Показали тестировщикам, как искать и проверять CSS селекторы в DOM дереве (в особо сложных случаях можно просто помочь и показать)
-
Настроили сборки в Jenkins для удобного запуска
и ... Завелось и поехало
Каждый из этапов можно описать подробно, но я не знаю на сколько это интересно (пишите в комментариях)
Важно. Мы не меняем методологию разработки внутри продукта. Т.е. мы не внедряем BDD/TDD подход полноценно
Мы просто используем существующий фреймворк этой методологии для разработки автотестов
Реализация
Чтобы долго не рассказывать как и почему - выложил рабочий пример в репозиторий simpleE2E
В публичный репозиторий вынесли несколько обрезанную версию нашей реализации. В ней убрано все, что касалось работы с api проекта (оставил только заготовки для примера) и шаги, включающие несколько действий внутри. Но в целом это полностью рабочий код с примерами тестов и универсальными шагами.
При необходимости можно брать и использовать: Клонируем репозиторий, выполняем инструкции из readme, пишем тесты и запускаем
В проекте используется python + playwright + gherkin + behave
Документация инструментов:
Пример готового теста
Примеры тестов в репозитории разработаны специально для демонстрации
Feature: Сайт.SaveLink
Scenario: Большая форма. Проверка обязательности полей. Email
Given Дефект "Неверный текст предупреждения"/"https://jira.example.com/"
Given Я открываю сайт "https://save-link.ru/"
When Я ввожу "Тест" в "Имя"/"#partner-name"
When Я ввожу "9001001010" в "Телефон"/"#partner-phone"
When Я нажимаю "Оставить заявку"/"[data-form="partnership-form"]"
Then Вижу в "Предупреждении для Email"/".email._error" текст ~ "Не может быть пустым"
Then НЕ Вижу "Заявка успешно отправлена"/".request-complete._open"
Другие примеры тестов см в /features/test в репозитории проекта
Доступные для использования шаги
Мы пишем тесты на русском языке, потому что команде проекта так удобнее. Технических проблем с запуском или поддержкой тестов из за русского языка замечено не было. При желании можно изменить текст шагов на английский язык
Шаги делятся на 3 типа:
Given - Предусловия. Например
Given Я открываю сайт "{url}"
Given Я создаю сущность тест с именем "{entity_name}"
...
When - Действия. Например
When Я нажимаю "{name}"/"{selector}"
When Я нажимаю "{button}" на клавиатуре
When Я нажимаю ПКМ на текст "{text}"
...
Then - Проверки или ожидания. Например
Then Вижу текст "{text}"
Then НЕ Вижу "{name}"/"{selector}"
Then Жду исчезновения прелоадера "{selector}"
Then Сравнить со скрином "{path_screen}"
...
Чтобы получить полный список доступных шагов. Выполнить:
python steps_bdd.py --output=available_steps
В результате работы скрипта будет создан файл index.html с перечнем всех доступных шагов. На момент написания статьи доступных шагов в публичном репозитории 41.
В нашем основном репозитории 114 шагов:
40 шагов это предусловия по созданию сущностей через API
10-14 шагов, которые группируют популярные действия
~20 шагов, выполняют действия в диалоговых окнах и iframe
Полный перечень доступных шагов из index.html (шаги публичного репозитория)
Дополнительные опции
-
Ключевые слова. В шагах для ввода текста (Я ввожу текст, я ввожу большой текст и т.д.) можно использовать ключевые слова:
random - слово будет заменено на сгенерированное: Autotest<метка времени><случайное число>
longName(N) - слово будет заменено на последовательность символов длинной N (последовательность статична)
Существует шаг сравнения скриншотов, с определенной точностью. В результате шага прикладывается скрин текущего состояния, скрин эталона и разница изображений
В коде приведены примеры вызовов api, но они представлены только для примера и неработоспособны. Желательно использовать предусловия для создания сущностей через api + удаление сущностей
После выполнения каждого действия теста выполняется скриншот состояния и прикладывается к отчету
Подключено аппаратное ускорение. Работает быстрее при наличии дискретной графики
Отчеты
Все результаты теста и прочие артефакты собираются в allure отчет (в публичном проекте все для этого подготовлено).
Allure Report существует в виде плагинов CI/CD и локального приложения. Allure отличный инструмент для визуализации результатов автотестов (если кто еще не знал)
Ещё скрины отчета
Итоги
Плюсы
Каждый сценарий автотеста можно повторить руками (и не только тестировщику), т.к. он написан на человекочитаемом языке
Разработка автотестов выполняется силами ручных тестировщиков. Их понимание тестов и вовлеченность на высоте (т.к. это сокращает их время на регрессионное тестирование и просто интересно)
Автотесты выполняются ежедневно (в Jenkins), дефекты находятся на ранних этапах разработки и лечатся еще ДО старта регрессионного тестирования
Опционально. В будущем может облегчить переход на BDD/TDD методологию разработки внутри всей команды
Скорость разработки автотестов. 900+ стабильных e2e теста (реально стабильных) за 3 месяца (разработка только в свободное от задач время тестировщиков)
После разработки сценария теста тестировщик проходит ревью у своего коллеги
Возможные минусы
Дублирование последовательностей действий (у нас редкий кейс). Решение - Если последовательность действий часто дублируется, то ее можно объединить в единый шаг или параметризировать тест (в публичном проекте присутствуют примеры параметризированных тестов)
Использование селекторов внутри шагов. Да, это плохо. Нет pageObject со всеми вытекающими. Но мы осознанно идем на этот шаг, т.к. у каждого элемента должен быть атрибут data-test-id. Если он "пропал" - дефект в разработку и тест снова работает (не всегда через 5 минут, но все же довольно быстро)
Использование разных селекторов для одного и тоже элемента. С наличием атрибута data-test-id у каждого элемента не проявляется
Если вы столкнулись или можете столкнуться с перечисленными минусами (а все остальное нравится) - это не повод отказываться от этой идеи. Один из вариантов решения - записывать селекторы в один/несколько json файлов и обращаться к элементам по именам, а не по селекторам.
strelkove
Интересно))) Но ИМХО, даже для тестировщиков далёких от программирования достаточно нормально описанных методов в Page типа click_save_button() и т.д. Метод говорит сам за себя, составить на основе таких шагов тест тем более не сложно.
kuzin_ivan Автор
Возможны вы правы, мое имхо несколько отличается) (не все тестировщики все-таки готовы к работе с кодом)
Плюс еще в том, что разработчики/аналитики/менеджеры тоже по отчету могут понять, что конкретно не работает (или работает) и попробовать разобраться, пока тестировщик занят