Меня зовут Виктория Дежкина, я отвечаю за тестирование ряда продуктов в Дирекции больших данных X5 Retail Group. В прошлой части статьи я начала рассказывать о том, как мы меняли процессы в команде продукта «Система автоматизации закупок торговой сети». Релизы продукта постоянно задерживались на несколько дней и часто выходили «сырыми». Мы изменили порядок выкладки кода и планирования задач, что позволило сократить релизный цикл на несколько дней, но нам еще предстояло выработать оптимальный формат постановки и приемки задач, установить точки тестирования в релизном цикле и научиться приоритизировать задачи по исправлению дефектов.
Формат постановки и приемки задач и дефектов
Способ постановки задачи во многом определяет, насколько быстро и правильно она будет выполнена. Описывать задачи можно по-разному, например, с помощью user stories, которые отражают потребность конечного пользователя системы. Звучит это примерно так: «пользователь хочет получать отчет по нажатию зеленой кнопки».
Минус этого подхода в том, что он не поясняет, что будет «под капотом» у этого решения. User stories оставляют разработчикам слишком много свободы, и иногда это становится проблемой: команда начинает изобретать велосипед или пилит что-то слишком трудоемкое. А учитывая, что в условиях быстрой разработки почти никогда не хватает времени на полноценное документирование, вы при таком подходе получаете загадочный код, сильно затрудняющий интеграцию в продукт новых разработчиков.
Мы обсуждали несколько вариантов оформления задач и дефектов и остановились на «гибридном» подходе: use case + технические подзадачи. Бизнес-заказчик пишет use case, то есть описывает варианты использования нового функционала, а аналитик с тестировщиком на основе этого составляют для разработчиков технически подзадачи. В описании задачи в Jira мы добавляем use case, из которого она сделана, или тест-кейс, позволяющий воспроизвести ошибку, при этом название и описание у основной задачи остается «человекопонятным».
Посмотрим, к примеру, что находится внутри у дефекта с названием «Пользователь не понимает, как обрабатываются ошибки, возникающие при выборе ставки на закупку». В описании задачи находятся:
- кейс, по которому можно воспроизвести ошибку;
- реальный и ожидаемый результат;
- подзадачи для бэкенда и фронтенда с четкими указаниями для разработчиков, что нужно поправить. «Бэкенд: для данного API отдавать на фронтенд соответствующий ответ» + матрица вариантов, показывающая, какие ответы должны быть в каждой из возможных ситуаций. «Фронтенд: для данного API в зависимости от ответа с бэка выдавать соответствующий текст ошибки» + матрица вариантов.
Когда разработчик заканчивает свою подзадачу, он ее просто закрывает. Если все подзадачи закрыты – дефект возвращается на ретест. При обнаружении дополнительных проблем снова создается соответствующая подзадача.
Получается соответствующее правило описания дефектов:
- Создать задачу с описанием функциональной проблемы, кейсом для воспроизведения ошибки и связкой с историей, в рамках проверки которой был найден дефект.
- Добавить к задаче две подзадачи для бэкенда и фронтенда. Подзадачи на фронтенд содержат в себе дополнительно информацию: на какой странице, в какой среде находится дефект, какой API или компонент отрабатывает некорректно, что конкретно надо исправить и ссылку на use case с описанием корректного поведения. Подзадачи на бэкенд содержат в себе описание того, на какой среде найдена ошибка, какой это API, какие параметры передаются, какой приходит ответ, причину, почему реализованная логика считается неверной со ссылкой на документацию, а также указания, что конкретно требуется изменить.
Также мы отказались от формирования AC (acceptance criteria) на нашем продукте, так как на этапе планирования обсуждаем не только то, что разрабатываем и тестируем, но и как.
Что это дало? Такой подход позволил нам в любой момент времени понимать, что не так с функционалом со стороны пользователя, в какой стадии работа над дефектом и в зависимости от нагрузки на бэк и фронт по-разному приоритизировать подзадачи к одному и тому же дефекту.
В итоге еще до начала разработки вся команда понимает, какая часть каждой задачи коснется лично его, а на выходе каждая задача содержит в себе информацию: как разрабатывалась, как тестировалась, есть ли по ней документация, а также что в ней корректировалось в процессе разработки.
Такой подход используется только на нашем продукте, потому что он оказался для нас наиболее удобным. В других продуктах Дирекции больших данных X5 используются свои схемы: например, User stories с AC.
Казалось бы, наш вариант вовсе не способствует ускорению разработки, потому что требует больше шагов, чтобы начать работу. Но это не так.
Мы организовали процесс таким образом, чтобы тестирование велось параллельно с разработкой. Благодаря этому разработчик не сидит без дела, пока тестировщик прорабатывает и максимально локализует задачу. Плюс мы всегда видим, какой конкретно разработчик работал над задачей, как ее реализовывал – это позволяет понимать в будущем, кто из разработчиков быстрее справится с новыми аналогичными проблемами. Логика проста: чем меньше разработчик занимается делами, не связанными напрямую с написанием кода, – тем лучше, а максимально точная локализация дефекта позволяет глубже продумать возможные связки и проблемы, вызванные конкретной ошибкой.
Также может возникнуть вопрос, не мешают ли правила, которые мы установили в нашем продукте, формированию единых стандартов тестирования и разработки в департаменте. На самом деле нет: общие правила департамента определяют, что должна содержать задача к определенной стадии разработки, и мы соответствуем этим требованиям, просто прорабатываем задачу на более ранних стадиях.
Моменты тестирования
Мы долго обсуждали вопрос, на каком же этапе проводить тестирование. Сначала была идея проверять каждую отдельную задачу в локальной ветке, но при таком подходе было бы невозможно проверить, как эти задачи работают вместе, и их конфликты обнаруживались бы только на этапе собранного релиза, когда менять что-либо поздно.
Поэтому мы договорились о тестировании каждой задачи по отдельности, но на одном тестовом стенде. Сначала мы хотели выкатывать несколько задач сразу, но выше я уже рассказывала, какие риски несет в себе эта идея. По одной намного быстрее. Это известный эффект: сокращение количества параллельных задач не замедляет, а наоборот ускоряет процесс. В Канбане, например, есть такая штука, как WIP-лимит (WIP – это work in progress), который ограничивает количество задач, решаемых одновременно каждой ролью.
В итоге мы установили пять точек, где тестировщики активно участвуют в процессе разработки:
- На этапе документации. Следим за тем, чтобы не возникало задач, конфликтующих с логикой того, что уже сделано, фиксируем подробности реализации каждой задачи.
- На этапе постановки задачи. Проговариваем с аналитиком все возможные связанные с задачей кейсы и учитываем их при формировании задачи
- На этапе планирования. Проговариваем, как планируемая реализация может зацепить связанный функционал и какие проблемы может принести. Согласовываем с продактом все критичные дефекты и дополняем спринт.
- На этапе подготовки к релизу. Проверяем итерационно каждую задачу на тестовом стенде, а в день до планируемого релиза собираем все задачи вместе и проверяем на одном стенде.
- После релиза. Проверяем, как релиз работает на проде.
На старте, когда у нас были релизы раз в 2 недели, схема работы выглядела вот так:
Стало (релиз раз в неделю):
Правила взаимодействия связки «бэкенд – тестирование – фронтенд»
Когда в API между бэкендом и фронтендом пересылается много разных данных, не всегда понятно, для чего они нужны и как взаимодействуют. Из-за этого на фронтенде могут происходить поломки. Например, с бэка передается номер калькуляции, demand cal. Номинально это один параметр, но для осуществления расчета вместе с ним с бэка должно «притягиваться» еще восемь полей. Если не передать их вместе с номером калькуляции, на фронтенде эта операция не выполнится.
Чтобы избежать таких ситуаций, мы стали описывать передаваемые параметры, указывая их в комментариях к подзадаче на разработку API в Jira, где объяснялось, какими данными будут обмениваться бэк и фронт. Пробовали вести описания всех API в фреймворке Swagger, но с его помощью при автоматическом формировании документации не получалось передать фронтенду, что именно бэк будет делать с переданными параметрами. Поэтому мы договорились, что, если речь о параметре, который не просто записывается на бэке, а использует другие параметры, необходимо описывать его назначение в задаче.
Также мы стали контролировать обозначение переменных, чтобы в однотипных API все поля были стандартизованы. Наш продукт состоит из микросервисов, и в каждом могут использоваться свои названия полей. В одном поле с названием поставщика может быть supplier, в другом – supplierID, в третьем name и т.д. При передаче этих данных в один компонент фронтенда могут начаться сложности, поэтому мы прошлись по всем параметрам и начали стандартизировать все названия переменных. Для этого собрали сводную таблицу всех текущих обозначений, таблицу всех компонентов фронта и используемые ими переменные (с чем сильно помог фронтенд-разработчик) и сверили их. Теперь все новые API получают стандартные названия переменных, а старые API правятся при возникновении задач на их доработку.
Ускорение работы по исправлению дефектов
На этапе постановки задачи приоритеты определяет бизнес-заказчик – ему виднее, что и в каком порядке нужно для развития продукта. Но после выкатки на dev, когда появляются задачи на исправление дефектов, их приоритетами командует тестировщик.
Иногда возникает необходимость срочно поменять приоритеты этих задач – например, мы обнаруживаем мелкий дефект на бэке, без исправления которого не может начать исправления команда фронтенда.
Раньше в таких ситуациях мы сразу шли к разработчикам и просили их поменять приоритет задач, но это их отвлекало. Поэтому мы договорились, что будем обращаться только в определенные моменты – после code freeze, до 5 раз в день. Что это дало? Мы перестали снижать продуктивность разработчиков внезапными обращениями, избавились от простоев, увеличили время для проработки задач аналитиком.
Более того, благодаря тому, что задачи теперь не появляются у разработчиков стихийно, мы всегда знаем, у кого какая загрузка, кто раньше работал над задачей и сможет быстрее с ней справиться. В результате намного лучше понимаем, успеем ли мы подготовить релиз по графику или нет.
Эти меры вместе с единой логикой выкатки кода на dev, релиз и прод позволили сократить период исправления дефектов с 3 дней до 3-4 часов.
Результаты
За 9 месяцев работы нашего продукта «Автоматизация закупок» у нас получилось сократить релизный цикл с 2,5 недель до 1 недели с возможностью ежедневной выкатки, значительно повысив стабильность релизов.
Что изменилось:
- Мы избавились от необходимости исправлять дефекты после разработки, так как по максимуму вынесли эту работу на этап подготовки задач.
- Сократили период исправления дефектов с 3 дней до 3-4 часов.
- Получили возможность выкатывать релизы «по команде». Теперь можем в любой день собраться, выкатить задачи, и к вечеру все будет готово и отлажено.
- Повысили прозрачность процессов для всех участников процесса: теперь все разработчики и тестировщики команды понимают, что происходит в данный момент, кто какими задачами занят, сколько еще времени нужно на разработку и исправление ошибок и т.д.
BONUS: удалось снизить уровень стресса в команде (я надеюсь), а еще благодаря согласованной работе команды (спасибо деливери) без проблем перейти на удаленку :-)
Внедряя эти улучшения, мы придерживались нескольких правил:
- Тестировщики и разработчики – в одной лодке (повторять это как мантру!), поэтому первое, что нужно сделать тестировщику – поладить с командой и узнать, что беспокоит ее больше всего, заручиться ее поддержкой. Моими союзниками и партнерами в команде стали деливери-менеджер и разработчики.
- Готового идеального решения нет, и его нужно искать. Тестировщик никому не навязывает свои правила, он подстраивается под команду и меняет свои подходы вместе с ней, держа при этом в голове образ светлого будущего и мягко внедряя меры для его достижения)).
- Слишком жесткие ограничения и стандартизация – не метод. Если переборщить, команды могут потерять гибкость.
Правила взаимодействия, которые помогли нам ускорить развитие этого продукта, нельзя в чистом виде перенести на другие продукты Дирекции – они устроены иначе, и потребности разработчиков там отличаются. Но принцип создания этих правил будет таким же: устанавливать порядок выкладки кода, находить оптимальные точки для тестирования, документировать код и API.
Параллельно с работой внутри продуктов мы вырабатываем правила, которые призваны облегчить взаимодействие между продуктами, и об этом мы обязательно расскажем в следующих материалах. Так в Дирекции больших данных постепенно формируется стратегия развития качества продуктов.
ivanych
Не вполне понимаю суть этого достижения. Почему не до одного дня? Зачем тянуть неделю?
X5RetailGroup Автор
Речь идет возможности разработки одного и того же объема нового функционала в более короткий срок. Выкладка проходит недельными циклами не из-за ожидания, а потому что продукт активно развивается и на каждом релизе добавляется крупный кусок нового функционала. Мелкие правки могут выкатываться ежедневно. Более сложные бизнес — задачи — раз в неделю.