Разделы портала

Онлайн-тренинги

.
Не автоматизируйте тест-кейсы
12.02.2024 00:00

Автор: Блейк Норриш (Blake Norrish)
Оригинал статьи: Tea-Time With Testers, #03/2021
Перевод: Ольга Алифанова

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

К сожалению, автоматизация тест-кейсов и продвижение метрик вроде «процента автоматизированных кейсов» – антипаттерн управления качеством, неминуемо приводящий к раздутым, сложным в поддержке наборам тестов, толку от которых немного. Автоматизация, безусловно, критически важна для гибких поставок, но упрощенный менталитет «фабрики автоматизации» – нездоровый подход к автоматизации тестирования.

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

Издержки и выгоды тест-автоматизации

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

Все автоматизированные тесты подвержены двум типам издержек: изначальные издержки на разработку, и текущие эксплуатационные издержки на поддержку. Ожидается, что тесты будут приносить выгоду – разницу между временем выполнения теста вручную и (предположительно) куда более быстрой автоматизированной проверкой. Есть и другие неосязаемые выгоды (это веселее, позволяет освоить ценные навыки, и т. д.), но здесь мы их не рассматриваем.

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


Вот что влияет на стоимость теста:

  • Наличие (или отсутствие) тест-фреймворка, куда будет добавлен тест
  • Чистота существующего тест-фреймворка и тест-набора
  • Простота настройки тест-состояний (например, тестовых данных) и возможность их настраивать
  • Доступность приемлемого тест-оракула
  • Изменчивость интерфейсов или функций, с которыми будет взаимодействовать тест
  • Стабильность окружения, в котором тест будет проводиться
  • Технические навыки QA-инженеров, создающих и поддерживающих автоматизацию.

Ниже – частичное перечисление того, что может повлиять на выгоду, которую мы получим от автоматизированного теста:

  • Ожидаемая частота прогона теста (при каждом коммите, ежедневно, при каждом релизе, и т. д.)
  • Время, в течение которого тест будет валидной проверкой тестируемой системы
  • Стоимость ручной валидации аналогичного теста
  • Устойчивость теста к ошибкам при ручном прогоне.

Оба эти списка неполны, и опытные инженеры-тестировщики, возможно, уже кричат «А как насчет АБВ?!» К счастью, для демонстрации, что на ожидаемые издержки и выгоды от теста влияет множество факторов, исчерпывающий список и не нужен.

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

Итак, полная стоимость не финализируется при создании теста – она меняется со временем. Если изобразить это графически, то стоимость среднестатистического автоматизированного теста будет выглядеть так:


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

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


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

Это ключевой момент: ценность автоматизированных тестов зависит от множества переменных, и в зависимости от этих переменных тесты могут иметь как положительную, так и отрицательную стоимость жизни, оцениваемую в сэкономленном времени.

Разнообразие автоматизированных тестов

Теперь давайте разберемся, как этот график будет выглядеть для разных типов автоматизированных тестов. Под типами тестов мы понимаем все – маленькие юнит-тесты на уровне кода, чуть более крупные «социальные» юнит-тесты, компонентные тесты (которые еще крупнее), высокоуровневые интеграционные тесты; тесты, обходящие интерфейс пользователя и напрямую взаимодействующие с API; тесты, имитирующие API и проверяющие только интерфейс; E2E-тесты, работающие с полным комплектом технологий, и т. д.

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

Исследование всех типов автоматизированных тестов, которые можно реализовать для нетривиальной архитектуры – не задача этой статьи. Чтобы не уклоняться от темы, рассмотрим два крайних случая – маленький юнит тест и большой, полноценный end-to-end (E2E) тест.

Как будет выглядеть уравнение для издержек и выгоды и график зависимости ценности от времени для юнит-теста? Уникальные характеристики юнит-теста таковы:

  • Обычно их можно написать за несколько минут, если не секунд.
  • Они должны быть нечувствительны к внешним состояниям: это значит, что они настраивают имитаторы, дубликаты, заглушки, чтобы детерминированно контролировать исполнение.
  • Их запуск занимает миллисекунды, а запуск набора юнит-тестов – секунды.
  • Как правило, они исполняются тысячи раз в день – не только в ходе CI/CD для каждого коммита, но и локально – разработчик запускает их по мере создания кода.
  • Даже при 100% покрытии юнит-тесты не могут утверждать, что приложение правильно работает – они валидируют только крошечные, конкретные детали.

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

График, вероятно, будет выглядеть так:


А что насчет самых крупных автоматизированных тестов, E2E? Как будет выглядеть график для них?

Ключевые моменты E2E-тестов:

  • На них по определению больше всего влияют состояния, и они требуют тщательной настройки и контроля данных.
  • Они запускаются в полноценном окружении. Части этого окружения, как правило, используются другими приложениями.
  • Они часто включают множество (десятки, сотни) последовательных шагов.
  • Они наиболее медленны, запуск может занимать минуты.
  • Как правило, они тестируют функциональность, затрагивая пользовательский интерфейс.
  • Как правило, они запускаются на поздних этапах CI/CD.
  • Это единственный тип автоматизированных тестов, демонстрирующий, что приложение работает именно так, как этого ожидает реальный пользователь.

Учитывая вышесказанное, график ценности E2E будет выглядеть примерно так:

 

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

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

Где автоматизировать

По своей природе E2E тесты дороги в создании и поддержке. Они всегда полагаются на большую часть состояний большей части систем (или же эти состояния на них влияют). Они больше подвержены влиянию временных интервалов, синхронизации, сети и внешних зависимостей. Как правило, они проверяют функциональность (всю или частично) через веб-браузер – устройство, предназначенное для взаимодействия с человеком, а не машиной. Так как они запускаются в полном окружении, то с шансами будут делить части этого окружения с другими тестами или пользователями, что, возможно, приведет к коллизиям и неожиданным результатам.

Все эти (и многие другие) причины приводят к тому, что большие тесты подвержены наиболее высокому риску, и их существование оправдывает только соответственно высокая потенциальная ценность: только E2E тесты демонстрируют, как в реальности работает полностью интегрированная система.

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

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

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

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


Не буду пытаться убедить вас, что ваш набор всегда должен в точности повторять пирамиду (Кент Доддс утверждает, что это приз, Джеймс Бах предпочитает модель круглой земли, а Джастин Сирлс вообще считает модель ненужной). Надеюсь, однако, что убедил вас, что любая тест-автоматизация несет риски, и нужно убедиться, что тесты создаются на подходящем уровне – это позволяет снижать и контролировать эти риски. Огромная часть работы автоматизатора (в сотрудничестве с остальной командой!) – это определить, какой конкретно тип теста здесь подходит и с большим шансом будет иметь позитивную стоимость.

Перефразирую: к любой автоматизации нужно относиться, как к инвестиции, а если конкретнее – как к рискованной инвестиции. Любой тип автоматизированного теста подвержен своим особым рискам; необходимо управлять общим риском и максимизировать ценность наших инвестиций, постоянно оценивая издержки и выгоды каждого типа автоматизированных тестов.

Фабрика автоматизации и тест-набор с тяжелым верхом

Вернемся к фабрике автоматизации!

Подумаем о юзер-стори, приемочных критериях и тест-кейсах, которые профессионал тестирования создает на их основе: какой тип автоматизированного теста, с вашей точки зрения, соответствует таким тест-кейсам? Если мы вслепую возьмем тест-кейсы и автоматизируем их, к какому типу будут, как правило, относиться такие тесты?

При применении популярных Agile-техник требования передаются тестировщикам в высокоуровневой форме и на ориентированном на пользователя языке (зачастую мы даже называем это «юзер-стори»). Подумайте об историях «Если – Когда – Тогда» и приемочных критериях «Как …, я хочу…., чтобы…».

Стори 1538 Просмотр предыдущих заказов

Как постоянный покупатель

Я хочу видеть свои прошлые заказы

Чтобы быстро перезаказать товары повторно

Если я на странице лендинга

Когда я кликаю на «Прошлые заказы»

Тогда я вижу список всех предыдущих заказов


Если я на странице лендинга

И у меня не было заказов ранее

Когда я кликаю на «Прошлые заказы»

Тогда я вижу сообщение «Нет предыдущих заказов»

Даже если стори – горизонтальный срез, описывающий поведение конкретного компонента (к примеру, API REST-сервиса), требования будут описаны на «языке пользователя» этого компонента. Следовательно, тест-кейсы, созданные на основании этой документации, будут естественным образом попадать в категорию более крупных и рискованных типов тест-автоматизации.

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


Второй, иногда столь же мощный, фактор, заставляющий автоматизаторов делать ложный выбор в пользу крупных E2E тестов, а не более мелких – это то, что далеких от технической стороны вопроса (а также некоторых технически подкованных) людей очень успокаивает знание, что тест-кейсы уже автоматизированы. К примеру, руководители бизнеса могут понять кейсы – кейсы описывают приложение на знакомом им языке. Знание, что эти кейсы проверяются автоматически, убеждает их, что разгневанные пользователи не позвонят им в два часа ночи. Куда меньше их утешает фраза «Команда разработки добилась 90% покрытия юнит-тестами».

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

Симптомы фабричного подхода к автоматизации

Использование фабричного подхода к автоматизации, когда на входе тест-кейсы, а на выходе автоматизированные тест-кейсы, приводит к крайне проблемным, но, к сожалению, распространенным симптомам:

  • Прогон тест-наборов занимает несколько часов, или же возможен только ночью.
  • Единственная задача команд автоматизации – исследовать и затем приоритезировать падения из прошлого запуска, и это занимает большую часть их времени.
  • Падения тестов, способ борьбы с которыми – просто перезапускать тест, пока он не сработает.
  • Удаление набора из CI/CD процессов, или вывод этого шага из блокеров.
  • Тест-наборы, которых разработчики избегают или просто отказываются прогонять, так как не доверяют результатам.
  • Наборы с тысячами тестов, рассованные по сотням папок (или даже разным репозиториям!), с дупликацией тестов, закомментированными тестами, а также тестами, про которые неизвестно, что они делают и как сюда попали.
  • Геркулесовы усилия инженеров-автоматизаторов, направленные на управление раздутым набором тестов или сокрытие сложностей под Gherkin (Cucumber, и т. д.)

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

Здоровая автоматизация

Ладно, так как же подойти к тест-автоматизации, чтобы избежать раздутого набора тестов?

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

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

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


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

  1. Добавляйте новые тесты на самом низком из возможных уровне.
  2. Обновляйте существующие тесты для покрытия новой функциональности.
  3. Удаляйте любые тесты, ставшие неактуальными или чрезмерными, или комбинируйте тесты.
  4. Тестируйте общий случай на высоком уровне, а затем сделайте вариации этого теста более мелкими, низкоуровневыми тестами.
  5. Добавляйте новые, высокоуровневые E2E тесты только в случае крайней необходимости.
  6. Внедрите новый тип автоматизированных тестов, если эту функциональность нельзя покрыть ни одним из имеющихся.
  7. Меняйте системную архитектуру, чтобы внедрять новый тип автоматизированных тестов.
  8. Постоянно и критически оценивайте здоровье полного набора всех типов автоматизированных тестов силами всей команды разработки.
  9. Пункт 7 выше заслуживает особого внимания – именно тут кроется критическая разница между здоровым и критичным подходами к автоматизации.

Мы, команды разработки, должны прекратить воспринимать тест-автоматизацию как нечто, применяемое к ПО только после того, как оно создано. Вместо этого нужно рассматривать ее как критически важную часть самого процесса разработки. Автоматизация должна выращиваться вместе с ПО, и требование автоматизируемости должно руководить системным дизайном и архитектурой так же, как и любое другое требование. Такой подход к автоматизации позволит внедрять небольшие, экономичные разновидности автоматизации, невозможные в системах, созданных без учета автоматизируемости. Здоровая архитектура проектируется, чтобы тестироваться, и роль автоматизатора – это и уведомление проектировщиков системы об этих требованиях, и создание автоматизации после того, как система готова.

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

Обсудить в форуме