Всем привет! Меня зовут Артем. Я Android QA Engineer в команде Банки.ру, и я сегодня хочу рассказать, как Allure помог нам оптимизировать работу с unit-тестами на Android и взаимодействие разработки и QA.

Контекст: где живут тест‑кейсы и как мы запускаем проверки

Тест‑кейсы у нас хранятся в Allure TestOps – здесь мы ведем регресс и фиксируем, что именно должно проверяться.

Allure TestOps – это платформа для управления тестированием. У нас она в первую очередь используется как TMS: там хранятся тест‑кейсы, поддерживается структура регресса и видно, что именно и в каком объеме нужно проверять.

Из основных возможностей, которые важны в контексте статьи:

  • хранение и организация тест‑кейсов (по разделам, наборам, регрессам);

  • запуски (launches) и история прогонов – можно смотреть результаты тестов по конкретному прогону и в динамике;

  • отчеты и фильтрация по фичам/тегам/статусам, чтобы быстро понимать, где проблемы;

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

Дальше в статье я буду говорить про Allure/TestOps именно в этом смысле: как про место, где тест‑кейсы и результаты прогонов можно собрать в одну картину и использовать в регрессе.

Сам Allure выглядит следующим образом:

Сборки и прогоны запускаем через Bamboo. Для тестировщиков это, по сути, способ взять нужный билд и прогнать проверки (например, Postman‑тесты). Unit‑тесты тоже можно было запускать из Bamboo, но отдельной нормальной отчетности по ним у нас не было: результаты не попадали в удобное место, где их можно быстро посмотреть и использовать в работе.

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

Проблема была в том, что мы не могли:

  • знать какие unit‑тесты вообще существуют и что именно ими покрыто, из‑за чего было сложно опираться на них при планировании и анализе качества;

  • быстро посмотреть, какие unit‑тесты уже написаны и что именно они проверяют;

  • оценить покрытие по функционалу/модулям (где всё закрыто, а где пусто);

  • связать юниты с тест‑кейсами в Allure TestOps и явно отметить, что проверка автоматизирована;

  • использовать результаты unit‑тестов как часть регресса, а не разбираться с ними вручную.

В итоге они на практике почти не влияли ни на регресс, ни на то, как мы распределяем время на проверки. Чтобы это исправить, нам нужно было сделать результаты unit‑тестов доступнее и прозрачнее для QA. Это позволило бы встроить их в обычный цикл работы: планирование → прогон → разбор результатов → решение, где нужно углубленно потестить руками.

Для этого понадобились три вещи.

  1. Публикация результатов unit‑тестов в Allure. То есть чтобы после прогона в Bamboo появлялся нормальный запуск в Allure, где видно: какие тесты выполнялись, что упало, что прошло, и к чему это относится.

  2. Аннотации (разметка) самих unit‑тестов. Аннотации – это короткие метаданные, которые отвечают на базовые вопросы: какой это модуль/фича, что именно проверяет тест и с каким тест‑кейсом он связан. Без них Allure будет показывать просто список методов и классов, что QA мало что дает. 

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

Загрузка unit-тестов в Allure

Чтобы unit‑тесты начали приносить пользу, сначала нужно было просто научиться видеть их результаты. Для этого мы настроили генерацию allure-results в проекте и загрузку этих результатов в Allure TestOps из Bamboo.

1) На стороне проекта

В Gradle подключили Allure и зависимости для unit‑тестов. После этого при прогоне юнитов в модулях начала появляться папка build/allure-results – то есть тесты стали отдавать результат в формате, который понимает Allure.

2) На стороне CI (Bamboo)

Дальше мы настроили Bamboo так, чтобы он:

  • собирал allure-results со всех модулей в одну папку;

  • загружал их в Allure TestOps в конкретный проект;

  • создавал запуск с понятным именем вида <план> - #<номер сборки>.

Также написали скрипт, который собирает результаты со всех модулей и загружает их в конкретный запуск. Логика простая: после прогона unit‑тестов в каждом модуле появляются свои build/allure-results, и их нужно собрать в одну общую папку, чтобы потом одной командой отправить в Allure TestOps.

В итоге после каждого прогона в Bamboo у нас появлялся запуск в Allure TestOps, где уже можно было нормально смотреть unit‑тесты: что прошло, что упало и в каком объеме. А уже следующим шагом мы занялись тем, чтобы эти тесты стали понятны и связаны с тест‑кейсами – через аннотации и линки.

Подготовка перед разметкой: оценка покрытия unit-тестами 

Прежде чем массово размечать unit‑тесты, я решил не идти «вслепую». Когда в проекте сотни (а у нас сильно больше) юнитов, быстро выясняется, что главная проблема даже не в аннотациях, а в том, чтобы вообще понять, что уже покрыто, что покрыто частично, а где пусто.

Сначала я прошелся по существующим unit‑тестам и собрал по ним базовую информацию в таблицу. В ней я фиксировал:

  • к какому экрану/фиче относится проверка;

  • как называется unit‑тест (класс/набор);

  • какие классы в коде он трогает (чтобы было понятно, что именно тестируем: use case, mapper, reducer, validator и т.д.);

  • коротко – что проверяется (чтобы потом легче было писать аннотации и привязки).

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

Дальше я добавил в эту же таблицу простую, но полезную классификацию – разложил экраны и фичи по категориям:

  1. Зеленые – unit‑тесты нужны.  Тесты есть, но они покрывают какую-то часть, которую можно дополнить для большего покрытия.

  2. Красные – unit‑тесты не нужны.  Места, где unit‑тесты либо бессмысленны, либо слишком дорогие в поддержке.

  3. Голубые – unit‑тесты нужны, но не в первую очередь. Потенциально полезно, но можно отложить: низкий риск, редкие сценарии, либо нет времени/приоритета.

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

Разметка unit-тестов

Результаты unit-тестов без разметки малоинформативны: смотреть можно, но пользоваться сложно. Поэтому следующий шаг был самый «земной»: привести их к виду, в котором они читаются не только разработчиками, но и QA.

Чтобы не распыляться на весь проект сразу, я выбрал два самых крупных модуля – МПК и КФ2. Именно там было больше всего unit‑тестов, а значит, и максимальный эффект от разметки можно было получить быстрее.

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

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

Мы с командой договорились о следующем наборе разметки, который реально поддерживать:

  • Epic – крупный модуль системы;

  • Feature – функциональность внутри Epic;

  • DisplayName – заголовок теста, отображается в отчете;

  • Description – описание сути проверки;

  • Story – функциональный блок или сценарий, к которому относится тест;

  • Step – шаг внутри теста, помогает детализировать выполнение;

  • Link – Добавление ссылки к тесту в отчете.

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

Флоу работы с Allure и Unit-тестами

Чтобы Allure по unit-тестам не превращался в «посмотрели один раз и забыли», мы встроили его в нормальный CI-флоу. Идея простая: разработчики пишут юниты, дальше автоматика сама прогоняет тесты, собирает результаты и складывает их туда, где их удобно смотреть всей команде. Ниже – схема, как именно у нас устроен этот конвейер и в каком порядке по нему движутся тесты и отчет.

За счет такого подхода отчет всегда актуальный, команда смотрит в одну точку, а лишних ручных действий практически нет.

Помимо того, что unit-тесты гоняются в процессе написания задачи, они еще запускаются отдельно в общем прогоне по всему приложению, который мы запускаем в 3 часа ночи по московскому времени. Результат такого прогона (как и все результаты прогонов unit-тестов) можно посмотреть в запусках Allure.

После того как прогон unit-тестов отрабатывает в Bamboo, самое полезное начинается не в логах, а в отчете. Мы настроили Allure так, чтобы его можно было открыть прямо из билда – без скачивания артефактов и без локальных плясок с генерацией репорта. В результате в Bamboo появляется отдельная вкладка Allure Report.

Как это выглядит в Bamboo
Как это выглядит в Bamboo

По факту эта страница закрывает сразу несколько вопросов «в одном окне». Во‑первых, появилась отдельная вкладка Allure в Bamboo, и это удобно: отчет живет рядом с билдом, к которому относится. Во‑вторых, слева есть навигационный блок – можно быстро переключаться между Overview/категориями/сьютами/графиками и не искать нужное по всему отчету.

Дальше по содержимому:

  • блок Executors показывает, каким инструментом запускались тесты (в нашем случае – Bamboo) и из какой ветки/контекста пришел прогон;

  • основной список Suites – это группировка тестов по исходному коду (по сути, по тестовым классам/наборам), поэтому падение обычно находится ровно там, где его ожидаешь – в конкретном модуле/компоненте;

  • блоки вроде Features by stories дают разрез по фичам/сценариям (если разметка это поддерживает), что помогает смотреть не только где упало, но и что именно накрыто тестами.

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

Как это выглядит в Allure
Как это выглядит в Allure

В Allure первое, что бросается в глаза – общая информация прогона: процент успешности, количество тестов и базовая статистика, запуск джобы. Дальше уже начинается основная часть, совпадающая с информацией из Bamboo, а именно features и suites. В карточке запуска есть ссылка на прогон в Bamboo, она сильно ускоряет расследование, потому что при необходимости можно в один клик перейти к сборке, посмотреть параметры запуска и логи.

Структура тестов
Структура тестов

Когда проваливаешься в конкретный запуск в Allure, начинается самое полезное – можно нормально посмотреть каждый unit-тест, а не просто увидеть «зеленое/красное».

Слева Allure показывает список/дерево тестов: как они сгруппированы, какие статусы, сколько времени выполнялись. По сути это навигация по прогону – когда тестов сотни, реально спасает.

Справа открывается карточка выбранного теста. И вот тут становится понятно, зачем мы вообще заморачивались с разметкой:

  • в центре видно «содержимое» теста: описание, условия, шаги/сценарий (в зависимости от того, что прокинули). То есть тест читается как понятная проверка – что проверяем, на каких данных и что ожидаем.

  • справа лежат те самые аннотации Allure (метки). По ним дальше уже удобно жить: фильтровать, искать, строить нужные разрезы по фичам/сценариям/компонентам.

Почему это важно: без аннотаций отчет превращается просто в длинный список названий, а когда метки проставлены, появляется структура и становится гораздо легче ориентироваться, особенно если ты не автор этих тестов. Allure в таком виде – это не «pass/fail ради галочки», а рабочий инструмент. Открыл запуск, быстро нашел нужный тест, увидел контекст и разметку – и уже понятно, куда дальше копать.

Возникшие проблемы

Когда мы внедрили разметку unit‑тестов и договорились линковать их с тест‑кейсами в Allure TestOps, выяснилось, что дальше процесс идет по двум разным сценариям – и один из них работает заметно хуже.

1) Старый функционал: ссылки на тест‑кейсы уже есть

С уже существующими фичами всё относительно просто. QA анализируют раздел, понимают, где нужны юниты, и заводят задачу разработчикам по шаблону: что проверяем, какие сценарии (позитивные/негативные/границы), ожидаемый результат. Главное – тест‑кейс в Allure уже существует, поэтому его можно сразу приложить и добавить ссылку в аннотацию (через @Link).

Дальше задача уходит к разработчикам, и они пишут unit‑тесты уже с аннотациями и готовой ссылкой. Этот процесс получился прямолинейным: есть ТК → есть ссылка → тест сразу оформлен правильно.

2) Новый функционал: тест‑кейсов еще нет, ссылаться не на что

А вот с новым функционалом начались сложности. Разработка делает фичу, параллельно пишет unit‑тесты – но тест‑кейсы в Allure TestOps на этот момент часто еще не заведены. Значит, разработчик физически не может проставить @Link: ссылки просто нет.

В результате получалась цепочка:

  • разработчики пишут юниты без @Link;

  • задача уходит в QA на тестирование;

  • после тестирования QA заводят/актуализируют тест‑кейсы и только потом могут связать их с юнитами;

  • связи добавляются вручную и пачкой отдельным коммитом «на все линковки».

Почему это стало проблемой

Так процесс неожиданно разделился на два мира:

  • Для старого функционала линковка происходит «по пути», сразу и правильно.

  • Для нового – превращается в отдельную рутинную активность: собрать список ТК/требований, сгруппировать по фичам или спринтам, пройтись по тестам и добавить @Link вручную.

Это не только дополнительное время. Главный минус в том, что до момента ручной привязки unit‑тесты остаются «без адреса»: их видно в Allure, они запускаются, но они не связаны с конкретными тест‑кейсами, и QA не могут полноценно использовать их в регрессе и в оценке покрытия. Плюс такие задачи легко откладываются – и через несколько спринтов образуется хвост из «недолинкованных» тестов.

В качестве решения мы договорились развести это по процессу. Для старого функционала задачи на написание/дополнение unit‑тестов мы начали складывать на доску «Автоматизация»: перед началом спринта приоритезируем их и только после этого кладем в спринт в виде нормального объема работ. Для нового функционала, где тест‑кейсов на момент написания юнитов еще нет, решили делать по‑простому: QA самостоятельно раз в какое‑то время (обычно после спринта) проходят по свежим юнитам и дописывают аннотации @Link уже по факту заведенных тест‑кейсов, чтобы не копился хвост «тестов без адреса».

Как это стало частью регресса: результаты и дальнейшие планы

Регресс в команде начал работать по новой логике:

  1. Появился первый «быстрый слой» перед ручной частью. У нас есть отдельный общий прогон всех unit‑тестов по приложению, а также прогоны по каждой сборке, связанные с фича-задачами. Это стало базовой точкой, на которую можно опираться: перед тем как углубляться в ручной регресс, мы смотрим, что по юнитам происходит в целом. Где они зеленые – там меньше ручной работы. То есть регресс перестал быть одинаково «плоским» по всем разделам – появилась возможность перераспределять внимание.

  2. Связка ТК и unit‑теста стала частью регресса как структуры, а не побочной активностью. После интеграции мы начали воспринимать линковку как обязательный элемент: проверка считается встроенной в регресс только если она привязана к тест‑кейсу и видна в Allure TestOps, а не просто «существует сама по себе» в коде. Это дало измеримый эффект. С момента интеграции команда написала 1 090 новых unit‑тестов — объём тестов почти удвоился. Сейчас всего 2 343 unit‑теста, из них 1 063 (45,4%) уже с Allure‑аннотациями и корректной разметкой.

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

  3. Изменился вход в задачи и в покрытие: стало проще видеть, где юниты нужны. За счет таблицы и разметки мы начали четче понимать, какие фичи/экраны покрыты, где покрытие частичное, а где пусто. В результате мы стали чаще ставить задачи разработчикам на написание юнитов для старых фич – потому что теперь это не «кажется, было бы неплохо», а видно по структуре и отчетам.

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

Отдельно заметно помогает ИИ – в первую очередь там, где раньше было много рутины: разметка unit‑тестов для Allure стала быстрее, а разработчики стали чаще и в большем объёме добавлять аннотации. Также ИИ помогает придерживаться одинакового формата названий и описаний, когда в Allure становится видно покрытие по фичам. QA получают более понятные результаты (не просто имена методов), и меньше времени уходит на уточнения «что именно проверяет этот тест и зачем он нужен».