Автоматизация тестирования: как избежать распространенных ошибок

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

Быть или не быть

Вам гарантированно нужна автоматизация тестирования, если:

  • У вас проект длительностью в год или больше. Количество тестов, которые нужно прогонять в рамках регрессии, стремительно растет, а рутину нужно искоренять в первую очередь. Тестировщики должны тестировать, а не проходить тест-кейсы.
  • У вас распределенная команда разработки либо в команде больше двух разработчиков. Разработчик должен быть уверен, что его изменения не сломают чужой код. Без авто-тестов он узнает об этом в лучшем случае через день-два, в худшем — от пользователей.
  • Вы поддерживаете несколько версий продукта и выпускаете патчи и сервиспаки под каждую из них. Тут все очевидно: тестирование на разных конфигурациях — это рутина, а рутину надо искоренять.
  • Вы разрабатываете сервис, основная задача которого — обработка и трансформация всевозможных данных. Заниматься ручным вбиванием в систему данных и визуальным анализом результатов или отправкой запросов и анализом ответов — это вообще не то, чем должны заниматься живые люди каждый день.
  • У вас аджайл с короткими итерациями и частыми релизами. Времени на ручной прогон регрессии в рамках спринта катастрофически нет, а знать, что всё в порядке в тех местах, куда не лазили тестировщики, необходимо.

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

Зачем вообще нужны авто-тесты

Любая автоматизация нужна, чтобы избавить человека от рутинной работы. Автоматизация тестирования — в том числе. Однако существует также ошибочное мнение, что авто-тесты должны полностью вытеснить труд ручного тестировщика, и тестировать продукт должны скрипты. Это, конечно же, ерунда. Никакой скрипт пока не в силах заменить живого человека. Никакой скрипт пока что не умеет тестировать. Всё что умеет скрипт — это повторять запрограммированные человеком действия и сигнализировать, что что-то пошло не так, то есть делать простые проверки. И скрипт умеет делать это быстро и без участия человека.

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

Почему ожидания не оправдываются

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

Управленческие решения — это тема для отдельной статьи, а пока я просто выделю самые вредные ошибки без объяснений:

  • Попытка сэкономить на найме специалистов в области автоматизации. Если менеджер считает, что он может отправить своих тестировщиков на курсы по Selenium и они ему сделают автоматизацию, то он не прав.
  • Попытка внедрить автоматизацию без грамотно продуманной стратегии и планирования, типа «Давайте будем внедрять, а там посмотрим». Или чего хуже — автоматизация ради автоматизации: «У соседа есть, и мне нужно; зачем не ясно, но нужно».
  • Слишком поздний старт: тесты начинают автоматизировать только тогда, когда тестировщики уже совсем загибаются.
  • Убеждение, что дешевле нанять студентов, которые будут кликать регрессию руками (то есть вообще не делать автоматизацию, притом что присутствуют все признаки проекта, которому нужна автоматизация).

Под инженерными решениями я понимаю те решения, которые принимают инженеры при разработке и внедрении стратегии автоматизации. Это выбор инструментов, видов тестирования, фреймворков и т.п.

Пройдемся по некоторым моментам с инженерной точки зрения.

Почему автоматизация только UI-тестов — зло

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

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

Нестабильны они потому, что тесты зависят от «верстки» интерфейса приложения. При изменении порядка следования кнопок на экране или добавлении/удалении какого-то элемента тесты могут сломаться. Инструмент автоматизации не может найти нужный элемент либо может нажать совершенно не ту кнопку, и логика теста изменится.

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

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

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

Что же делать

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

Первое, что нужно в общем случае — это договориться с разработчиками, чтобы они не забывали прописывать для элементов уникальные атрибуты, по которым инструмент автоматизации может их однозначно идентифицировать. То есть, нужно по максимуму отказаться от пятиэтажных xPath-выражений или CSS-селекторов, и, по возможности, везде использовать уникальные id, name и т.п. Это должно быть явно прописано в девелопмент-гайдах и выступать одним из пунктов в definition of done для разработчиков. Тогда даже в случае капитального переколбаса пользовательского интерфейса у вас есть шанс отделаться легким испугом.

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

Тестируемое приложение должно давать возможность себя протестировать. Если такой возможности нет, то приложение нужно либо модифицировать, либо выбросить.

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

Ускоряемся. Если с нестабильностью всё достаточно просто, то проблема медленных тестов должна решаться комплексно, так как она влияет на процесс разработки в целом.

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

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

Третье и самое радикальное — создавать как можно меньше UI-тестов. Меньше тестов — раньше получаем результат их прогона.

Пирамида тестирования

Все помнят знаменитую пирамиду тестирования?

Если под маленькую пирамиду на ночь положить тупую бритву, то к утру она снова станет острой ©.

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

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

Что происходит, когда тот же тест автоматизирован через UI? Всё так же надо ждать, пока соберется и задеплоится новая версия, потом ждать, пока завершатся тесты. Потом надо проанализировать результаты прогона. Если были проблемы — определить, где эти проблемы возникли: в самом тесте или в приложении. Потом нужно еще раз прогнать упавший тест руками, чтобы наверняка понять, в чем проблема. Завести тикет, подождать пока пофиксят, перезапустить тест, убедиться, что теперь тест зеленый, закрыть тикет. Опять же — от пары часов до пары дней/недель. Плюс только в том, что этот тест автоматический, и пока он работает, тестировщик тестирует что-то другое.

Другая история, когда есть автоматизированные тесты, которые используют API для общения с бек-эндом приложения. Тут уже есть вкусные варианты:

— Тесты гоняются на полностью задеплоенном приложении со всеми внешними системами. По сравнению с чистыми UI-тестами, сильно сокращается время выполнения и анализа результатов, так как тут гораздо меньше ложно-позитивных срабатываний. В остальном всё так же, как и в UI-тестах.

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

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

Очевидно, что чем ниже спускаться по пирамиде, тем быстрее будут выполняться соответствующие авто-тесты. А значит, появляется возможность прогонять гораздо больше тестов за то же время. Соответственно, чем ниже уровень, тем более эффективные тесты можно на нем создавать в контексте времени отклика и величины покрытия.

Комплексный подход

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

UI-тесты же тестируют целостную систему, именно то, что будет использовать пользователь. Критически важно иметь такие тесты в наличии.

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

Test Driven Development — это уже даже не рекомендация, это должно исходить от разработчика по умолчанию. Только тогда можно избежать головняков при рефакторинге и типичных проблем разработки в больших командах.

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

На уровень UI-тестов выносятся исключительно приемочные тесты, так называемые Happy Path или End-To-End сценарии, которые показываются во время демо. Это относится как к веб-, так и к мобильным приложениям.

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

Резюме

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

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

Похожие статьи:
У новому випуску YouTube-рубрики «X питань», де ми розпитуємо представників різних спеціальностей про те, що турбує IT-спільноту, DOU...
После обсуждения наиболее распространенных вопросов по основам Java в первой части и двум популярным фреймворкам во второй...
7 вересня в телеграм-каналі DOU відбувся войсчат про бронювання від мобілізації. Обговорювали, наскільки складно зараз...
Регистрация обязательна Напоминаем, что участие в #TechTalks бесплатное, но количество мест ограничено — успейте...
274-й выпуск подкаста «Откровенно про IT карьеризм». В подкасте пойдет речь о достижениях Харьковского...
Яндекс.Метрика