Не автоматизируйте тест-кейсы |
12.02.2024 00:00 | ||||
Автор: Блейк Норриш (Blake Norrish) Использование тест-кейсов в качестве бэклога для тест-автоматизации – очень распространенная практика. QA разрабатывают тест-кейсы на основании юзер-стори в ходе обычного тестирования, а затем автоматизируют эти тесты. В каждой последующей итерации тестируется больше стори, автоматизируется больше тест-кейсов, и набор автоматизированных тестов растет. Ведущие инженеры продвигают метрики вроде «процента автоматизированных кейсов» и поощряют добившихся высоких показателей. В некоторых командах даже нанимают специализированных «инженеров-автоматизаторов», чья единственная задача – взять тест-кейсы и автоматизировать их. К сожалению, автоматизация тест-кейсов и продвижение метрик вроде «процента автоматизированных кейсов» – антипаттерн управления качеством, неминуемо приводящий к раздутым, сложным в поддержке наборам тестов, толку от которых немного. Автоматизация, безусловно, критически важна для гибких поставок, но упрощенный менталитет «фабрики автоматизации» – нездоровый подход к автоматизации тестирования. В статье мы продемонстрируем, почему фабрики автоматизации заблуждаются, и опишем подход к разработке автоматизации, при котором тест-автоматизация поддерживает и увеличивает скорость поставки. Издержки и выгоды тест-автоматизацииЧтобы понять, почему автоматизация существующих кейсов так проблематична, нужно сделать шаг назад, к обзору теории автоматизации. Если конкретнее, нужно разобраться в издержках и выгодах тест-автоматизации, взглянуть на ожидаемую с течением времени ценность автоматизированных тестов, а затем понять, как эта ожидаемая ценность меняется в зависимости от типа тестов. Затем посмотрим, как автоматизированные тест-кейсы, применяющие простой «фабричный» подход, влияют на тест-наборы в целом. Все автоматизированные тесты подвержены двум типам издержек: изначальные издержки на разработку, и текущие эксплуатационные издержки на поддержку. Ожидается, что тесты будут приносить выгоду – разницу между временем выполнения теста вручную и (предположительно) куда более быстрой автоматизированной проверкой. Есть и другие неосязаемые выгоды (это веселее, позволяет освоить ценные навыки, и т. д.), но здесь мы их не рассматриваем. Это, конечно, страшно упрощенный взгляд на тест-автоматизацию, но для наших целей критично важные моменты тут учтены – любой автоматизированный тест любого типа имеет как издержки, так и выгоды, и оба момента важны. Как эксперты автоматизации, мы стремимся максимизировать выгоды и минимизировать издержки. Вот что влияет на стоимость теста:
Ниже – частичное перечисление того, что может повлиять на выгоду, которую мы получим от автоматизированного теста:
Оба эти списка неполны, и опытные инженеры-тестировщики, возможно, уже кричат «А как насчет АБВ?!» К счастью, для демонстрации, что на ожидаемые издержки и выгоды от теста влияет множество факторов, исчерпывающий список и не нужен. Мы уже постановили, что издержки автоматизации можно разделить на собственно разработку и стоимость постоянной поддержки. У выгод тоже есть измерение времени: ценность автоматизированного теста извлекается не сразу, а накапливается в ходе жизни теста. Итак, полная стоимость не финализируется при создании теста – она меняется со временем. Если изобразить это графически, то стоимость среднестатистического автоматизированного теста будет выглядеть так: На графике показан тест, исходно имеющий отрицательную нетто-стоимость: исходные затраты на разработку перевешивают выгоды от сэкономленного времени. Однако мало-помалу сэкономленное время превосходит и изначальные затраты, и затраты на поддержку, и дает положительную стоимость. Каждый тест проходит через примерно такой жизненный цикл, завися от перечисленных выше факторов. В зависимости от исходных затрат на разработку, затрат на поддержку, и полученной выгоды тест может пройти точку безубыточности намного раньше, или же никогда ее не достичь: На графике выше показан тест, который исходно был чем-то полезен (после разработки линия идет вверх), но затем перестал приносить выгоду. Возможно, его перестали запускать, или из-за его нестабильности ему не доверяли, или тестируемая им функция вышла на пенсию. Вне зависимости от причин график говорит нам, что лучше было бы вообще не автоматизировать этот тест. Это ключевой момент: ценность автоматизированных тестов зависит от множества переменных, и в зависимости от этих переменных тесты могут иметь как положительную, так и отрицательную стоимость жизни, оцениваемую в сэкономленном времени. Разнообразие автоматизированных тестовТеперь давайте разберемся, как этот график будет выглядеть для разных типов автоматизированных тестов. Под типами тестов мы понимаем все – маленькие юнит-тесты на уровне кода, чуть более крупные «социальные» юнит-тесты, компонентные тесты (которые еще крупнее), высокоуровневые интеграционные тесты; тесты, обходящие интерфейс пользователя и напрямую взаимодействующие с API; тесты, имитирующие API и проверяющие только интерфейс; E2E-тесты, работающие с полным комплектом технологий, и т. д. Важно отметить, что в сложном современном ПО можно реализовать огромное количество типов автоматизированных тестов; количество способов декомпозиции системы на составные части и изоляции того или иного участка почти безгранично. Каждая из таких изоляций – возможный тип теста. Исследование всех типов автоматизированных тестов, которые можно реализовать для нетривиальной архитектуры – не задача этой статьи. Чтобы не уклоняться от темы, рассмотрим два крайних случая – маленький юнит тест и большой, полноценный end-to-end (E2E) тест. Как будет выглядеть уравнение для издержек и выгоды и график зависимости ценности от времени для юнит-теста? Уникальные характеристики юнит-теста таковы:
Учитывая вышесказанное, график ценности юнит-теста, вероятно, сильно отличается от нашего «среднестатистического» графика: затраты на разработку практически отсутствуют, поддержка нужна минимальная, и несмотря на очень частый запуск, каждый отдельный прогон реально приносит малую выгоду. График, вероятно, будет выглядеть так: А что насчет самых крупных автоматизированных тестов, E2E? Как будет выглядеть график для них? Ключевые моменты E2E-тестов:
Учитывая вышесказанное, график ценности E2E будет выглядеть примерно так:
Этот график показывает значительно большие изначальные затраты, исходно опуская стоимость в отрицательные глубины. Однако постоянный запуск такого теста со временем позволяет ему пройти точку безубыточности и стать поставщиком позитивной стоимости. Повторюсь – ожидание, что со временем тест достигнет позитивной стоимости, основано на предположениях, сделанных в начале этого раздела: как долго тест будет использоваться, как часто будет запускаться, насколько мы уверены в его результате, какие изменения ему понадобятся из-за изменений в задействованных интерфейсах (вроде UI); насколько стабильно окружение запуска, и т. д. Никто не гарантирует, что тест достигнет точки безубыточности. Где автоматизироватьПо своей природе E2E тесты дороги в создании и поддержке. Они всегда полагаются на большую часть состояний большей части систем (или же эти состояния на них влияют). Они больше подвержены влиянию временных интервалов, синхронизации, сети и внешних зависимостей. Как правило, они проверяют функциональность (всю или частично) через веб-браузер – устройство, предназначенное для взаимодействия с человеком, а не машиной. Так как они запускаются в полном окружении, то с шансами будут делить части этого окружения с другими тестами или пользователями, что, возможно, приведет к коллизиям и неожиданным результатам. Все эти (и многие другие) причины приводят к тому, что большие тесты подвержены наиболее высокому риску, и их существование оправдывает только соответственно высокая потенциальная ценность: только E2E тесты демонстрируют, как в реальности работает полностью интегрированная система. Рассматривать можно и многие другие типы тестов, а в сложных системах высока вероятность того, что тест более низкого уровня будет напрямую тестировать необходимую функциональность, не требуя издержек, ассоциированных с более высокоуровневыми, крупными тестами. Иными словами, не пишите API-тест для валидации участка логики, который можно проверить при помощи юнит-теста. Не пишите E2E-тест на логику, которую можно проверить одним API-запросом. Никогда не задействуйте больше участков системы, чем вам действительно требуется, проверяя, работает ли что-то. Выявите логику или поведение, нуждающиеся в тесте, и создайте тест, изолирующий именно это. Используйте высокоуровневые тесты только для настоящей проверки интеграции, а не логики компонентов. Самый главный момент: E2E-тесты подвержены высокому риску, и редко будут наилучшим типом автоматизации для тестирования конкретной функциональности. Возвращаясь к логике зависимости стоимости от времени: всегда выбирайте типы тестов, дающих наивысшую немедленную ценность с наименьшими затратами, и скептично относитесь к огромным потраченным на автоматизацию усилиям, оправданным только чересчур оптимистичными оценками времени, которое мы когда-нибудь сэкономим. Такой анализ затрат и издержек много лет назад и привел к концепции пирамиды тест-автоматизации. Пирамида утверждает, что при прочих равных нам обычно нужно больше маленьких, быстрых и дешевых тестов, и гораздо меньше медленных и дорогих. Не буду пытаться убедить вас, что ваш набор всегда должен в точности повторять пирамиду (Кент Доддс утверждает, что это приз, Джеймс Бах предпочитает модель круглой земли, а Джастин Сирлс вообще считает модель ненужной). Надеюсь, однако, что убедил вас, что любая тест-автоматизация несет риски, и нужно убедиться, что тесты создаются на подходящем уровне – это позволяет снижать и контролировать эти риски. Огромная часть работы автоматизатора (в сотрудничестве с остальной командой!) – это определить, какой конкретно тип теста здесь подходит и с большим шансом будет иметь позитивную стоимость. Перефразирую: к любой автоматизации нужно относиться, как к инвестиции, а если конкретнее – как к рискованной инвестиции. Любой тип автоматизированного теста подвержен своим особым рискам; необходимо управлять общим риском и максимизировать ценность наших инвестиций, постоянно оценивая издержки и выгоды каждого типа автоматизированных тестов. Фабрика автоматизации и тест-набор с тяжелым верхомВернемся к фабрике автоматизации! Подумаем о юзер-стори, приемочных критериях и тест-кейсах, которые профессионал тестирования создает на их основе: какой тип автоматизированного теста, с вашей точки зрения, соответствует таким тест-кейсам? Если мы вслепую возьмем тест-кейсы и автоматизируем их, к какому типу будут, как правило, относиться такие тесты? При применении популярных Agile-техник требования передаются тестировщикам в высокоуровневой форме и на ориентированном на пользователя языке (зачастую мы даже называем это «юзер-стори»). Подумайте об историях «Если – Когда – Тогда» и приемочных критериях «Как …, я хочу…., чтобы…».
Даже если стори – горизонтальный срез, описывающий поведение конкретного компонента (к примеру, API REST-сервиса), требования будут описаны на «языке пользователя» этого компонента. Следовательно, тест-кейсы, созданные на основании этой документации, будут естественным образом попадать в категорию более крупных и рискованных типов тест-автоматизации. Это ключевая проблема фабричного подхода к автоматизации – автоматизация тест-кейсов неминуемо ставит во главу угла большие, медленные и дорогостоящие тесты, потому что тест-кейсы, что естественно, пишутся на языке ручного тестировщика. Они соответствуют именно тому типу тестов, которых наш анализ зависимости стоимости от времени советует избегать! Второй, иногда столь же мощный, фактор, заставляющий автоматизаторов делать ложный выбор в пользу крупных E2E тестов, а не более мелких – это то, что далеких от технической стороны вопроса (а также некоторых технически подкованных) людей очень успокаивает знание, что тест-кейсы уже автоматизированы. К примеру, руководители бизнеса могут понять кейсы – кейсы описывают приложение на знакомом им языке. Знание, что эти кейсы проверяются автоматически, убеждает их, что разгневанные пользователи не позвонят им в два часа ночи. Куда меньше их утешает фраза «Команда разработки добилась 90% покрытия юнит-тестами». Следовательно, ряд людей будет выступать в поддержку таких метрик, как процент автоматизированных тестов и количество автоматизированных тестов, потому что так им комфортнее понимать, в каком состоянии тестирования – и вовсе не потому, что это действительно наиболее эффективный и продуктивный метод автоматизированной проверки поведения системы. Стремление к автоматизации каждого кейса, возможно, даст вам ощущение безопасности, но не приведет к здоровому автоматизированному тест-набору. Симптомы фабричного подхода к автоматизацииИспользование фабричного подхода к автоматизации, когда на входе тест-кейсы, а на выходе автоматизированные тест-кейсы, приводит к крайне проблемным, но, к сожалению, распространенным симптомам:
Все эти симптомы сигнализируют о тест-наборе, который не приносит пользы своей команде – это, к сожалению, часто встречается в организациях, разрабатывающих ПО. Страдающие команды добросовестно приоритезировали тест-автоматизацию в своем процессе разработки, но подошли к ней с наивным менталитетом фабричного подхода. Здоровая автоматизацияЛадно, так как же подойти к тест-автоматизации, чтобы избежать раздутого набора тестов? Нужду в автоматизации, покрывающей новую функциональность, нужно оценивать целостно, рассматривая возможности автоматизации для каждого типа тестов. Вы совершенно точно не должны предполагать, что новая функциональность непременно нуждается в новом максимально высокоуровневым автоматизированном E2E-тесте. Вместо этого оцените, как наиболее эффективно и продуктивно покрыть эту функциональность при помощи полного набора из всех типов тестов. Вам не нужно автоматизировать тест-кейсы – вам нужно автоматизировать функциональность. Ее можно частично описать тест-кейсами, но автоматизация каждого дискретного кейса, превращение его в отдельный автоматизированный тест на том уровне, на котором его выполняет ручной тестировщик, никогда не будет ни эффективным, ни продуктивным делом. На самом деле наиболее эффективный способ тестирования новой функциональности – это, вполне возможно, обновление уже имеющегося автоматизированного теста, его перемещение в более подходящий тип тестов, или даже создание нового типа тестов. Не забывайте, что с внедрением изменений в функциональность системы вы должны не только добавлять новые тесты, но и удалять существующие! Тип нужного вам теста, конечно, будет сильно зависеть от системной архитектуры, допустимых рисков, существующих инструментов, и т. п. Обобщенный здоровый подход к изменению автоматизации будет выглядеть примерно так:
Мы, команды разработки, должны прекратить воспринимать тест-автоматизацию как нечто, применяемое к ПО только после того, как оно создано. Вместо этого нужно рассматривать ее как критически важную часть самого процесса разработки. Автоматизация должна выращиваться вместе с ПО, и требование автоматизируемости должно руководить системным дизайном и архитектурой так же, как и любое другое требование. Такой подход к автоматизации позволит внедрять небольшие, экономичные разновидности автоматизации, невозможные в системах, созданных без учета автоматизируемости. Здоровая архитектура проектируется, чтобы тестироваться, и роль автоматизатора – это и уведомление проектировщиков системы об этих требованиях, и создание автоматизации после того, как система готова. Понимание, что автоматизация имеет свою цену, и эта цена создает риски; что функциональность нужно тестировать разными типами автоматизированных тестов; что проблема тест-автоматизации – это грамотное управление этими типами тестов с целью создания цельного, наиболее эффективного и продуктивного набора тестов; и осознание, что автоматизируемость не менее важна, чем любое другое требование к дизайну системы – вот здоровый подход к тест-автоматизации. А создание фабрик автоматизации и слепая автоматизация всех тест-кейсов, превращение их в новые высокоуровневые автоматизированные тесты – подход нездоровый. |