Оглавление
Введение.
Подготовка мануальных тестов.
Внедрение идентификаторов для HTML элементов.
Подготовка Python методов.
Подготовка автотестов.
Зависимости между тестами.
Взаимодействие (интеграция) с QASE.
Результаты.
Введение
Шесть месяцев назад на Habr была написана первая статья по этой теме. В ней описаны процессы, позволившие запустить автотестирование имеющегося web-приложения. Текущая статья описывает доработанный подход к тестированию того же web-приложения.
Стек
TypeScript на фронте.
MongoBD, Python, ElasticSearch на бэкенде.
Selenium, Python, Pytest, Selenoid в автотестах.
Подготовка мануальных тестов
Тестируемое web-приложение представляет из себя продукт с достаточно сложной логикой и большим количеством путей, которыми пользователи могут достичь результата.
Первым делом были написаны мануальные тест кейсы, в соответствии с которыми мануальные тестировщики могли проводить регрессионное тестирование. В течение нескольких следущих регрессий тест кейсы были доработаны. Сейчас это список из 642 тестов, написанных в QASE. В момент проведения регрессии невалидные тест кейсы вручную помечаются, чтобы затем их актуализировали и доработали. Так список поддерживается в актуальном состоянии.
Внедряем идентификаторы для HTML элементов
В процессе написания мануальных тест кейсов формируется список элементов WEB-страницы, с которыми в процессе тестирования взаимодействует мануальный тестировщик. Речь идет о кнопках, ссылках, картинках, текстах на WEB-страницах.
Список элементов необходим для того, чтобы автотест мог повторить каждый шаг мануального тестировщика самостоятельно и убедиться в наличии ожидаемого результата.
Результат, который будет достигнут к завершению этой статьи выглядит следующим образом: автотесты выполняют действия, описанные в мануальных тест кейсах и проверяют наличие ожидаемого результат. Если ожидаемый результат отсутствует, то автотест сообщит об ошибке. Таким образом снимается нагрузка с мануальных тестировщиков, а автоматическая проверка имеющегося функционала проводится при каждом внесении изменений в GitHub, сразу сообщая разработчикам о возможных багах.
Каждый элемент WEB-страницы помечается data- атрибутом с понятным человеку наименованием. У нового функционала фронт разработчики сразу прописывают data- атрибуты, тем самым функционал готов к автоматизации без лишних запросов со стороны автоматизаторов. Для ранее разработанного функционала, где data- атрибутов нет, тестировщиками формируется список элементов и далее разработчики по списку проставляют атрибуты.
Подготовка Python методов
Python методы обеспечивают взаимодействие с элементами WEB-страницы. В данном случае речь имет о методах, которые чаще всего выступают в качестве обетки для Selenium методов, дополняя их возможности. Примеры:
click
- используя данный python метод автотест может кликнуть по заданному элементу WEB-страницы (клик по кнопке, например).openPage
- используя данный python метод автотест может открыть в новой вкладке браузера заданный адрес (например: открой в новой вкладке https://google.com).enterValue
- используя данный python метод автотест может вставить заданное значение в input (например: вставь значение "Илья" в поле "Имя" формы регистрации).
Каждый метод отражает одно действие, которое мануальный тестировщик соверщает с элементами WEB-страницы в процессе мануального тестирования. Наши автотесты могут использовать 13 действий, вот полный список:
openPage
открывает заданный адрес;click
кликает по веб элементу;enterValue
вставляет значение в заданный input;clearValue
удаляет текущее value из заданного input;pressKeyboardNumbers
имитирует нажатие клавиш клавиатуры;select
выбирает в выпадающем списке заданный элемент);collectText
сохраняет текст с WEB-страницы в переменную для дайнейшего использования другими методами;collectValue
сохраняет value тега в переменную для дальнейшего использования другими методами;compareVariable
сравнивает текст на WEB-странице со значением из переменной;compareText
сравнивает тест на WEB-странице с заданным текстом;file
вставляет заданный файл в форму выбора файла;findElement
является прямым аналогом Selenium метода find_element;wait
является прямым аналогом time.sleep().
Имеющиеся в распоряжении методы позволяет покрыть 80% действий пользователя с интерфейсом web-приложения. Для специфических тестов дописываются новые методы.
Подготовка автотестов
Мануальные тесты написаны в QASE. Здесь же пишутся автотесты.
Автотест предстаставляет из себя набор последовательных действий с элементами WEB-страницы. На каждой новой строке автотеста указываются действие и сопутствующие ему данные.
Сопутствующие данные
У каждого действия определены сопутствующие данные. Несколько примеров:
openPage
требует адрес открываемой страницы;click
требует идентификатор элемента, по которому должен произойти клик;select
требует индетификатор выпадающего списка и значение, которое должно быть выбрано.
Для того, чтобы при написании автотеста не забывать сопутствующие данные, в QASE прикреплена заметка с подсказками:
openPage
[URL]click
[selector_id]select
[selector_id, value]clearValue
[selector_id]enterValue
[selector_id, value]pressKeyboardNumbers
[value]collectValue
[selector_id, variable_title]collectText
[selector_id, variable_title]compareVariable
[variable_title, value]compareText
[selector_id, value]file
[sector_id, file_name]findElement
[selector_id]wait
[time in seconds]
Зависимости между тестами
В начале пути у нас был выбор из двух вариантов. Кратко о каждом варианте ниже.
Писать каждый автотест полностью независимо. Указывая полный набор действий. Так, для теста с проверкой поля "Имя" в форме редактирования профиля пользователя, потребовалось бы написать следующие действия:
написать все действия, связанные с регистрацией пользователя;
написать все действия, создающие профиль пользователя;
написать действия проверки формы редактирования профиля и поля "Имя" в частности.
В виду того, что автотестов по теме редактирования профиля пользователя больше 10, все они потребовали бы написания большого количества однотипных подготовительных действий - preconditions.
В ситуации, когда флоу регистрации пользователя изменился, пришлось бы вручную переписывать все 10 автотестов по теме редактирования профиля пользователя. Кроме того, при изменении флоу регистрации пользователя все 10 автотестов редактирования профиля пользователя упали бы, показывая ошибки в одном из действий.
Делать зависимые тесты. При таком варианте прекондишены каждого теста состоят из набора ранее писанных тестов. В указанном выше примере получилась бы следующая структура:
Preconditions:
Автотест регистрации пользователя.
Автотест создания профиля.
Call:
Автотест проверки редактирования профиля пользователя.
При такой структуре прекондишены набираются из уже существующих тест кейсов и это уменьшает время на разработку тест кейса проверки редактирования профиля пользователя.
Второй важный момент заключается в том, что при изменении флоу регистрации пользователя достаточно будет поправить один тест кейс регистрации пользователя, чтобы вернуть работоспособность всем тест кейсам связанным с проверкой редактирования профиля пользователя.
Третий важный момент проявляется при падении тестов. Если ошибка произойдет на этапе прекондишена, то сам тест кейс будет считаться заблокированным, а не упавшим. А значит сократится время на разбор результатов тест рана и исправление ошибок.
В работе мы используем второй вариант.
Взаимодействие (интеграция) с QASE
Что хранится в QASE:
Код автотестов;
Результаты каждого автотеста;
Результаты каждого тест рана.
Интеграцию осуществляли через API QASE с бесплатным аккаунтом.
Процесс взаимодействия тестового сервера (или локальной машины) и QASE происходит следующим образом:
Создаем в QASE новый тест план с указаем автотестов, которые хотим прогнать;
-
На тестовом сервере настраиваем cron, который раз в 5 минут проверяет список тест планов в QASE и при наличии нового тест плана начинает следующий процесс:
Получает список тест кейсов из тест плана;
Создает в QASE новый тест ран с указанным списком автотестов и удаляет тест план, так как он больше не нужен;
Стартует прогон автотестов скачивая из QASE список действий для каждого автотеста;
По завершении каждого автотеста отправляет в QASE результат (успешно, упал, блокирован). Если упал, то прикладывает логи;
По завершении всех автотестов завершает тест ран.
По завершении тест рана QASE отправляет в Slack красивый отчет о тестировании.
Выше описан ручной старт автотестов. Помимо него при поступлении webhook от GitHub тест план создается уже по команде от тестового сервера, а дальше все как в ручном старте.
Результаты
Трудозатраты со стороны автоматизаторов кроются в следующих задачах:
Написание python методов.
Доработка интеграции с QASE.
Разбор ситуаций, когда тест падает по какой-то неочевидной проблеме.
Трудозатраты мануальных тестировщиков:
Написание мануальных тестов в QASE.
Написание автотестов в QASE.
Ручной запуск автотестов при необходимости.
Актуализация автотестов при изменении продукта.
За счет выноса процесса написания автотеста из кода в стороннюю систему удалось снизить затраты на содержание большой команды автотестирования. Многие действия, связанные с автотестами могут выполняться мануальными тестировщиками.
Разработка нового автотеста занимает до 30 минут с учетом нескольких прогонов созданного теста на разных стендах.
Формирование отчетов о тестировании полностью автоматизировано от момента сбора данных о падении теста и до момента публикации итогового отчета в Slack.