И снова в нашей ленте «Календарь тестировщика». В этом месяце Марина Третьякова, тестировщик проекта Контур.Поставки, расскажет об оптимизации тестов. Марина разберет конкретные проблемы и способы их решения, а также посоветует, как оптимизировать свои тесты и сократить время на тестирование.
Прежде всего давайте разделим всё тестирование по степени автоматизации, чтобы в дальнейшем рассматривать каждый тип более детально.
По степени автоматизации тесты делятся на:
- Ручные.
- Автоматизированные.
- Автоматические (без участия человека, на данный момент – скорее миф нежели реальность).
Подход к оптимизации тестов напрямую зависит от степени их автоматизации.
Оптимизации, применимые ко всем видам тестов
Тестирование включает в себя этапы:
- подготовка тестируемой системы,
- подготовка входных данных,
- проведение тестов (вручную или автоматизированно, рассмотрим ниже),
- сбор и анализ результатов.
Считается, что больше всего времени у тестировщиков отнимает ручная регрессия. Однако, в большинстве случаев это не так. Как минимум, не стоит это утверждать, пока проблема не измерена и не доказана.
Рассмотрим решения типичных проблем. Многие советы могут показаться вам крайне очевидными, но как показывает опыт конференций и выступлений коллег из других компаний, данные советы всё же актуальны и доказали свою применимость и полезность.
Проблемы:
1. Долгая подготовка тестируемой системы
Вопросы, которые важно задать до внедрения оптимизаций:
- Долгая относительно чего?
- Кто занимается этой подготовкой (тестировщики, программисты…)?
- Сколько раз при желании можно за рабочий день подготовить тестируемую систему? Соответствует ли это число потребностям тестирования?
- Какой этап в подготовке самый долгий и почему?
Чтобы найти причину этой проблемы, важно задать правильный вопрос.
Рассмотрим примеры:
Долгая компиляция всех модулей системы
Правильный вопрос: нужна ли компиляция всех модулей?
Решение: компилировать не все модули системы, а лишь те, которые были затронуты в задаче, и которые будут участвовать в релизе.
Долгий ручной процесс обновления всей системы по разным «виртуалкам» на тестовом стенде
Правильный вопрос: в какой момент обновления требуется участие человека, а в какой нет?
Решение: автоматизировать процесс выкладки, использовать специальные инструменты деплоя и раскатки сервисов либо отлаженные механизмы релиза на «боевую», но применять их только для деплоя на тестовую.
Долгий процесс «разлития» исходников по «виртуалкам» на тестовом стенде для дальнейшей компиляции и раскатки
Вероятная проблема: сетевое взаимодействие.
Правильный вопрос: долгий относительно чего (сбора на локальной машине, сбора в локальной сети)?
Решение: тестовый стенд и то место, где лежат исходники, должны находиться в одной сети, чтобы минимизировать сетевое взаимодействие.
С этой проблемой я сталкивалась в работе, когда решили сменить тестовую площадку в Екатеринбурге на московскую. И в процессе проб “выкладки” сайта мы быстро заметили, что обновление стенда стало занимать уже не 3 минуты, а почти 15 минут. Причина оказалась в том, что исходный код с большим количеством мелких файлов находился в Екатеринбурге, а стенд в Москве. Процесс выкладки “уперся” в сетевую передачу мелких файлов для дальнейшей компиляции и “выкладки” на стенд. В результате код тоже “уехал” в Москву :)
2. Долгий сбор и анализ результатов
Вопросы, которые важно задать до внедрения оптимизаций:
- Долгий относительно чего?
- Из каких этапов состоит процесс сбора и анализа результатов? Какой именно этап самый долгий и почему?
- Кто анализирует результаты?
- Кто принимает решение о релизе и на основании чего? Сколько тратит времени на принятие решения?
Например:
Результаты тестирования оформляются по шаблону, оформление по шаблону отнимает большУю часть времени при тестировании.
Решение (спасибо, Кэп!): отказаться от заполнения результатов по шаблону либо создать более легкий для заполнения шаблон. Потребуется договориться с командой и узнать у тех, кто читает эти результаты (а читают ли их?), действительно ли есть потребность именно в таком шаблоне (риск – писать «в стол» результаты тестирования).
Оптимизации, применимые к ручным тестам
Эти тесты можно разделить на два больших класса:
- проводимые регулярно, например, перед релизом (считай, регрессионное тестирование),
- проводимые редко и только для проверки новой функциональности.
Если регресс проводится часто и вручную, то имеет смысл задуматься об автоматизации и окупаемости автоматизации, но в рамках данной статьи мы не будем рассматривать ROI автоматизации.
Для тестов проводимых вручную (не регрессионных) следует говорить не об автоматизации тестирования, а об инструментальной поддержке тестирования (как советовал Алексей Баранцев на тренинге, который проводил у нас в компании). В этом случае автотесты будут выступать в роли инструмента. В данном контексте изменится логика и взгляд на автотесты в целом.
При тестировании, проводимом вручную, прежде всего требуется искать рутинные задачи (задачи, а не тесты!), и уже оптимизировать их (с использованием автоматизации либо перераспределением человеческих ресурсов).
Например, рутинной задачей для тестов является подготовка тестовых данных. Есть разные способы проводить эту самую подготовку:
- вручную через UI,
- вручную через API,
- с помощью запуска автотестов, тогда данные будут побочным эффектом этих тестов,
- автоматизированно через скрипты/утилиты/самописные инструменты через API или UI.
Если вы никогда не задумывались, сколько времени у вас занимает ручная подготовка тестовых данных, то может пора это измерить? И окажется, что гораздо эффективнее использовать, как минимум второй, а лучше 3-й и 4-й подходы.
Оптимизации, применимые к автоматизированным тестам
Проблема подготовки тестовых данных здесь стоит острее, нежели при ручном тестировании. Подготовка тестовых данных должна быть:
- быстрой,
- устойчивой к изменениям дизайна/верстки,
- устойчивой к возможным параллельным запускам тестов,
- устойчивой к изменениям внутренней архитектуры системы.
Желательно, чтобы подготовка данных не требовала дополнительных навыков и времени при реализации решения.
Тестовые данные автоматизированно можно подготовить:
- через UI,
- через API или HTTP-запросы,
- через запросы к базе данных.
Рассмотрим плюсы и минусы этих подходов подробнее в таблице:
![](https://habrastorage.org/webt/rv/4c/8y/rv4c8ypxlb7spceq380djrc7upu.png)
Подготовка тестовых данных через API или HTTP-запросы по совокупности плюсов и минусов является самой оптимальной.
Есть ряд наиболее распространенных оптимизаций, применимых к тестам, проводимым автоматизированно:
Параллельность тестов
Если одной из проблем тестов является именно время их прохождения, при этом есть вычислительные ресурсы, можно распараллелить и выполнять их в одном из трех режимов параллельности:
- Параллельность на одном компьютере, параллельность по потокам процессора.
- Параллельность на разных компьютерах.
- Комбинация первого и второго способа, то есть при наличии нескольких компьютерных машин тесты проходят параллельно по потокам на каждой и параллельно среди всех машин.
Удаление старых тестов
Если тесты написаны, проходят, но уже толком не проверяют ничего (например, раньше была бизнес-логика, теперь ее нет и тесты по сути ничего уже не проверяют), то такие тесты нужно безжалостно удалять, ведь по сути они не несут никакой смысловой нагрузки, отнимая лишнее время от прогона. Также стоит удалить тесты, результат прохождения которых никак не влияет на принятие решения о возможности релиза.
Применение техник тест-дизайна для оптимизации наборов тест-кейсов
При ручном тестировании для оптимизации наборов тест-кейсов требуется применять различные техники тест-дизайна. Для автотестов также следует применять методы разбиения на классы эквивалентности, pairwise, анализ границ и многие другие техники, чтобы оптимизировать набор автотестов.
Перенос существующих тестов и проверок на другой уровень
Например, есть браузерный тест, который открывает поисковую строку, вводит “яблоко”, “яблоки”, “яблоку”, “яблок” (и так далее), и смотрит, что при совершении поиска ему показалось уведомление о покупке яблок в магазине (тест смотрит на сам факт показа уведомления и не больше). Таким образом, долгий тест на UI по сути своей UI не проверяет, он проверяет логику, которую может проверить модульный тест, поэтому данный тест следует удалить и написать вместо него модульный тест.
Правильная декомпозиция тестов по уровням “модульные — интеграционные — системные”
Приведу пример. Есть ручной сценарий: выбрать товар в интернет-магазине, положить его в корзину и перейти к оформлению заказа. Что можно сделать (и это будет неправильно): создать ровно один тест, который будет искать товар, добавлять его в корзину и переходить к оформлению.
Правильным будет в данном случае разделить сначала тест на три подсценария: выбор товара, добавление товара в корзину, оформление заказа. Каждый сценарий разделим на более атомарные проверки.
Например: “открытие магазина — отображение разных категорий товара для выбора” — один тест; “выбор категории из разных категорий товара” — другой тест. Каждую проверку рассматриваем более детально и определяем, какого уровня тесты для нее нужны, предыдущий пример может подсказать, какого типа тесты лучше сразу оформлять как модульные.
Популярная схема связей тестируемой и тестирующей систем при автоматизированном тестировании web-приложений:
Для оптимизации автоматизированного тестирования web-приложения целесообразно рассматривать оптимизацию каждого взаимодействия в описанной схеме.
![](https://habrastorage.org/webt/e8/7c/g2/e87cg2ftp026bsuwdxb1ufe4clm.png)
Для простоты рассмотрим оптимизации некоторых взаимодействий:
1) Взаимодействие “test-cases — browser — database”
Использование API не только для подготовки данных для теста, но и для проведения ряда шагов в тесте.
Например, если цель – проверить UI в конце длинной цепочки действий, то вовсе не обязательно все действия проводить через UI. Ведь если посередине цепочки в UI что-то поломалось, тест так и не дойдет до конца и целевой проверки. Тестировщик так и будет гадать, а если починят это сломанное звено цепочки, то всё, что после него работает ли? Если в данном случае на протяжении всей цепочки кроме последнего действия использовать API, то при UI-поломке любого звена тестировщик будет знать, будет ли работать система так, как задумано, если разработчики починят сломавшееся звено.
2) Взаимодействие “test-cases — SeleniumWebDriver — browser”.
- Закрытие лишних вкладок по завершению теста, вместо закрытия браузера.
На моем проекте данная оптимизация помогла сэкономить 10 минут в прогоне UI тестов (вместо 1ч.10 мин. тесты стали проходить за 1ч.). Данная оптимизация связана с логикой работы SeleniumWebDriver, который используется на проекте – у него очень долгая подготовка открытия браузера, а вот закрытие вкладок происходит практически мгновенно. - Оптимизация кэша приложения тестируемой системы, чтобы тесты проходили быстрее.
- Использование headless браузеров, чтобы не было затрат на рендеринг элементов веб-страниц.
В заключение
Для любой оптимизации нужно четко для себя определить текущие проблемы в процессе тестирования, по пунктам разложить в чем они заключаются, представить возможные варианты (лучше несколько!) их решения. После этого требуется озвучить их в команде, «продать» свои идеи и предложения по решению, и только лишь после всеобщего одобрения распределить усилия и решить поставленные задачи. Предварительная оценка “До” и оценка “После” помогут рассмотреть все выигрыши от оптимизации процессов.
И еще раз хотелось бы повториться: не ищите рутинные тесты, ищите рутинные задачи, и автоматизируйте их!
Список статей календаря:
Попробуй другой подход
Разумное парное тестирование
Обратная связь: как это бывает
Оптимизируй тесты
Прочти книгу
Тестирование аналитики
Тестировщик должен поймать баг, прочитать Канера и организовать движуху
Нагрузи сервис
Метрики на службе у QA
Протестируй безопасность
Узнай своего клиента
Разбери бэклог