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

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

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



Переход от водопада к скраму


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

Мы ввели скрам-мероприятия и короткие итерации. В теории всё выглядело хорошо:

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

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

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

Этапы QA-процесса


Kick-off встреча, example mapping, приёмочные сценарии


Продакт-менеджер приносит в команду user story или техлид приносит техническую историю развития компонента.

В первую очередь нужно декомпозировать историю. Для этого:

  • Команда формирует единое для всех участников понимание требований к истории, в том числе с помощью исчерпывающего количества вопросов продакт-менеджеру. Заодно это помогает находить требования, которые не были учтены изначально. Для встреч мы используем фреймворк example mapping (карта тест-кейсов), который значительно повышает их эффективность. Важно не применять фреймворк формально, без понимания его работы, потому что он не сработает, а у команды возникнет негатив к подобным изменениям. Подробнее об example mapping: на русском, на английском.
  • UX-дизайнер проектирует пользовательское поведение и создаёт мокапы.
  • Разработчик проектирует техническую сторону реализации.
  • QA-инженер вырабатывает критерии приёмки для каждой истории и на их основе создаёт приёмочные сценарии: не черновик, а полный список тестов, которые надо провести, чтобы быть уверенным, что всё проверено.

Приёмочные сценарии (acceptance criteria/ definition of done)— не просто список тест-кейсов, а результат исчерпывающей детальной декомпозиции задачи, после которого у вас должно возникнуть состояние «здесь больше нечего обсуждать».



Backlog Grooming и Sprint Planning


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

Покрытие тестами — неотъемлемая часть задачи, а написание тестов — нормальная работа разработчика. Но к этому ещё не все привыкли, поэтому покрытие тестами лучше брать в спринт явно хотя бы на первых этапах. Сейчас, к счастью, мы уже сталкиваемся со случаями, когда разработчики сами напоминают, что по определённой задаче сценарии не проработали.
Если мы вводим ограничения и правила (например, нельзя мерджить задачу, если не автоматизированы и успешно пройдены все acceptance scenarios), то единственный способ ускорить time to market — повышать качество. Мы можем быстрее, только если мы можем качественнее.

Повышение качества позволяет сократить количество итераций и времени на разработку. На нашем опыте это позволяет уменьшать время разработки более чем в 2 раза.



Непосредственная разработка и ручное тестирование


Здесь главная сложность — большое количество итераций разработки. Например, одна из фич в нашем продукте прошла 26 итераций. Почему? Потому что раньше в процессе разработки инженер вместо самостоятельного тестирования отдавал код сразу QA, что часто приводило к наличию ошибок и множеству доработок.

Это могло выглядеть так:

  1. Разработчик реализует задачу, но не тестирует её тщательно, так как знает, что за ним всё проверит QA-инженер.
  2. QA-инженер находит ошибки и возвращает задачу на доработку.
  3. Разработчик правит найденные ошибки, но допускает новые.
  4. Цикл многократно повторяется.

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

Что с этим делать? Мы могли передать ручное тестирование с QA-инженеров на разработчиков, но это могло привести к потере качества. Изменения в процессах нужны тогда, когда они гарантируют повышение качества результата. Поэтому мы не просто убрали ручное тестирование, а заменили его новыми задачами, дающими лучшее качество:

  • Подготовка приёмочных сценариев, благодаря которым разработчик точно знает, что нужно проверить, и у него есть все возможности сделать это.
  • Покрытие тестами на разных уровнях. Релизим мы ежедневно, а изменения в код вносят порядка 30 команд. При этом наши сайт, фронтенд и бэкенд — это три монолита, которые разделены на модули и компоненты, но всё равно есть взаимосвязи, способные сломаться.
  • Автоматизация тестирования. Мы покрываем тестами сразу во время разработки, для этого все QA-инженеры в компании умеют писать автотесты. В разных командах покрытие тестами устроено по разному: в одних командах все виды тестов пишут разработчики (юнит-тесты, интеграционные, компонентные, модульные, e2e), в других QA покрывает тестами API или готовит все автотесты.
  • Проверка позитивных сценариев вместе с продакт оунером. Это позволяет команде лучше понимать замысел постановки и еще раз покачать историю.
  • Проверка вёрстки и дизайна. Этот этап происходит совместно с дизайнером и клиентским разработчиком до мерджа реквеста.

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

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



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

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

Благодаря этим изменениями мы реализуем как простые, так и большие сложные задачи (например, месяц работы 5 инженеров) мы реализуем за считанное количество итераций, часто за одну. Мы внутри договорились, что задачи на бекенде должны реализовываться за 1-2 итерации, на сложном фронте — максимум за 5 итераций. Если количество итераций растёт — это сигнал для нас, что присутствует процессная проблема.

Фиче-галочка и исследовательское тестирование


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

Большая фича обычно реализуется несколькими людьми, представляет собой последовательность задач, релизится на продакшен частями, а сама функциональность изначально скрыта от пользователей (мы используем для этого “фиче-галочку”). Когда фича на продакшене, но ещё скрыта от пользователя, QA-инженер проводит все исследовательские тесты, которые были проработаны на грумминге: нагрузочное тестирование, тестирование безопасности, conduct consumer testing и т.д. Например, он может выделить время и целенаправленно поломать готовый функционал целиком. Для этого у QA всё есть: он понимает его устройство, так как детально изучал его на установочных встречах и при создании приёмочных сценариев, и у него не замылен взгляд, так как он почти не участвовал в процессе разработки.

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

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



Релиз и мониторинг


После того, как все исследовательские тесты проведены, мы релизим функционал на пользователей (снимаем “фиче-галочку”), а команда начинает мониторить фичу. Сам процесс релиза состоит из нескольких стадий, но об этом я напишу в другой раз.



Кратко обо всём, что мы изменили в процессе тестирования


Тестирование теперь происходит не в конце спринта, оно распределено на весь спринт.

За качество результата отвечает не QA-инженер, а вся команда. Раньше QA брал на себя ответственность за всё, сделанное командой, потому что только он занимался тестированием и отдавал команду на релиз. Теперь у всех появилась своя роль в поддержке качества:

  • Дизайнер отвечает за консистентность UX в продукте и удобство использования фичи;
  • Разработчик отвечает за покрытие тестами, в том числе за e2e;
  • QA-инженер отвечает за хитрые кейсы взаимосвязи с другими частями системы и различные подходы тестирования, которые помогают протестировать фичу целиком;
  • Продакт-менеджер делает так, чтобы команда реализовывала ту фичу, которая действительно необходима пользователям. А точнее, что фича после заработки отвечает всем критериям, которые были задуманы.

Вся схема QA-процесса в удобном для просмотра формате