В прошлом году нашей QA-команде нужно было интегрировать Allure TestOps в проекты. До этого никто из нас этим не занимался, но вместе разобрались и сделали. Я осознал, что в одиночку потратил бы на это очень много времени или вообще бы не разобрался, потому что инструкции, как это сделать, не было. Поэтому написал свою, в надежде, что она будет полезна тем, кто окажется в такой же ситуации.
В общем, если вы тестируете бэкенд на .NET, а для сборки проектов используете GitHub Actions и хотите внедрить Allure TestOps — эта инструкция для вас.
Allure TestOps — это Test Management System (TMS), которая изначально строилась с фокусом на автоматизацию и подход «тест-кейсы как код». Конечно же, это не случайно, т.к большинство автоматизаторов используют Allure Report и в коде автотестов уже используются механизмы разметки отчётов — эти же механизмы используются и для интеграции с Allure TestOps.
Недавно мы закончили интеграцию c Allure TestOps, и я решил написать инструкцию, как быстро и легко затащить к себе этот инструмент, если вы раньше никогда такого не делали.
Из чего состоит Allure TestOps
Для начала давайте посмотрим, что внутри.
Allurectl — это CLI-интрефейс-обёртка над API Allure TestOps, которая умеет управлять тест-кейсами, лончами и другими сущностями и загружать результаты тестов в TestOps.
Allure Report — бесплатный инструмент, который формирует и визуализирует отчёты по прогонам автотестов. Существуют реализации для большинства языков и тестовых фреймоврков. Мы используем реализации для C#, JS, Kotlin и Swift.
Allure TestOps — платный инструмент, который использует механизмы формирования отчётов Allure Report для интеграции между тестами и самой TMS. По ним формируются тест-кейсы, статистика и т.д. Во главу угла ставит подход «тест-кейсы как код».
Для чего внедрять Allure TestOps
Allure TestOps стоит внедрять, если мы хотим:
иметь единое место для всех отчётов о прогоне. Например, наши микросервисы собирались в GitHub Actions (GHA), а монолит — в TeamCity. Это уже было проблемой, потому что результаты прогонов тестов были в разных местах. Нужно было собрать информацию о запусках тестов в одном месте. А так же хотелось легко видеть причину падения, success rate тестов и тесты, упавшие по одной причине;
перестать писать ручные тест-кейсы или сократить их написание до минимума;
избавиться от ручной поддержки тест-кейсов;
чтобы метрики собирались автоматически. Например, нам нужны были метрики success rate тестов и длительность прохождения теста, и в GHA их не было.
Наш стек
Я тестирую преимущественно бэкэнд, написанный на .NET, поэтому примеры будут на .NET + NUnit + Speclow. Для сборки проектов мы используем GHA.
Общие шаги
Давайте верхнеуровнево рассмотрим шаги, которые нужны для интеграции Allure TestOps с автотестами.
Получить пробную версию Allure TestOps.
Выполнить первичную настройку проекта в Allure TestOps.
Подключить к проекту с тестами зависимости на Allure Report.
Разметить автотесты атрибутами.
Настроить директорию для хранения allure-result.
Добавить в CI шаги по работе с allure-results.
Запустить тесты, дождаться их прохождения.
Получаем пробную версию Allure TestOps
Выбираем self-hosted или cloud-версию, запрашиваем доступы к пробной версии (обычно их дают на месяц). Всё, что мы сделаем в пробной версии, сохранится при покупке полной версии, и мы продолжим использовать уже настроенные проекты и интеграции.
Выполняем первичную настройку проекта в Allure TestOps
-
Создаём проект. В Allure TestOps это продукт или сервис, на который мы написали автотесты, лежащие в конкретном репозитории.
-
Настраиваем правила генерации тест-кейсов. Мы оставили генерацию через 24 часа и только из лончей с тегом
master
(tag is master). Тегом master помечены lounches из мастер-ветки. Все тесты, запущенные на мастер-ветке, будут генерироваться в тест- кейсы. Вы можете указать свою основную ветку.
Мы генерируем только из основной ветки, потому что в фича-ветках могут быть ещё не законченные тесты и в нашу документацию будет попадать незаконченная дичь. Отложенная генерация на 24 часа нам нужна, потому что разработчики иногда перезапускают упавшие билды на следующий день. И если lounch уже закрылся, они не могут перезапустить билд. -
Если хотим, чтобы тесты помечались слоями, например system (за это отвечает атрибут
[AllureLabel(”layer”, “system”)]
) — добавляем это в настройки. -
Настраиваем свой способ построения дерева тест-кейсов. Мы используем такой: Suite1 (атрибут ParentSuite) → Suite2 (атрибут subSuite) → Suite3 (у нас нет третьего уровня, но в настройке указали сразу, вдруг появится).
-
Настраиваем связку атрибутов из автотестов с кастомными полями. Мы сделали связку атрибута ParentSuite в Suite1 и subSuite в Suite2.
Подключаем к проекту с тестами зависимости на Allure Report
Устанавливаем нужные Nuget-пакеты. Для чистого nUnit — Allure.NUnit, а для SpecFlow — Allure.Specflow.
Если вы используете «маки», вас ждёт прикол: Allures зависят от пакета AspectInjector, и если вы не установите этот пакет явно, то проект перестанет собираться локально.
Размечаем тесты атрибутами
Nunit
Самое важное для NUnit — проставить атрибут [AllureNUnit] в каждом тестовом классе. Без этого Allure не поймёт, что ему нужно взять этот тест и сделать из него allure-results.
SpecFlow
Для Specflow ничего размечать не нужно, он сразу увидит автотесты, шаги в них и сгенерирует результаты.
А дальше всё зависит от наших потребностей. Мы разметили сьюты, чтобы группировать тесты. В своём проекте я разметил ещё и слои тестов, но профита от этого не получил.
Настраиваем директорию для хранения allure-result
Чтобы настроить пути к allure results, нужно добавить в корень проекта с автотестами файл allureConfig.json
и указать там путь к директории с результатами запуска тестов. Если этого не сделать, то по умолчанию результаты будут генерироваться в директории путь_до_проекта_с_тестами/bin/Release/net6.0/allure-result
(в зависимости от конфигурации запуска тестов вместо Release может быть Debug. В одном проекте я обнаружил, что тесты запускались с конфигурацией Debug, поэтому адрес был bin/Debug/net6.0/allure-result
). Мы обычно просто в конфиге указываем что-то подобное:
{
"allure": {
"directory": "../../allure-results"
}
}
При такой конфигурации директория allure-result
создастся в директории bin
и путь до результатов будет, например, bin/allure-result
.
Обязательно нужно указать, чтобы файл allureConfig.json
копировался при сборке проекта. Делается это с помощью нажатия правой кнопкой мыши на файл — Properties — Copy to output directory — Установить параметр Copy always. Если этого не сделать, то allure results будут складываться в директорию по умолчанию.
Добавляем в CI шаги по работе с allure-results
Мы используем в качестве CI GitHubActions, поэтому примеры актуальны для него.
В первую очередь необходимо добавить в GitHub секреты, которые нам отправили при покупке Allure TestOps.
Отредактируем наш workflow билд. Это .yml-файл, который лежит в repository_name/.github/workflows/
.
Что нужно обязательно там сделать:
-
установить переменные окружений из секретов. Можно установить их в глобальных переменных или в переменных конкретного шага — запуска тестов.
ALLURE_LAUNCH_TAGS
— тег запуска тестов, будет нужен дальше,ALLURE_LAUNCH_NAME
— имя запуска тестов, будет нужен дальше;
-
подготовить allurectl к работе, указав id проекта, версию allurectl. Мы используем официальное решение https://github.com/marketplace/actions/setup-allure-testops.
ALLURE_ENDPOINT
— эндпоинт возьмётся из секретов.ALLURE_TOKEN
— токен возьмётся из секретов.
У нас шаг выглядит так:
- name: Setup Allure TestOps uses: allure-framework/setup-allurectl@v1.0.0 with: allure-endpoint: ${{ secrets.ALLURE_ENDPOINT }} allure-token: ${{ secrets.ALLURE_TOKEN }} allure-project-id: 3 allurectl-version: 1.23.0
Версию лучше указывать явно. При обновлении что-то может сломаться и мы сразу получим неработающую сборку. У нас возникла проблема: на релизе 2.0+ версии allurectl перестала формироваться ссылка на запуск. Если бы мы не указали версию, в один момент у нас бы сломались ссылки на запуски во всех проектах;
-
залить результаты в
allure storage
. На этом шаге остановимся подробнее. Есть 2 варианта загрузки результатов:с помощью
allurectl watch
. Эта команда оборачиваетdotnet test
и выполняется вместе с ней. Результаты в реальном времени подгружаются в облако;
- name: Run backend component tests id: component-tests run: allurectl watch --results src/Dodo.Tracker.ComponentTests/bin/allure-results -- dotnet test --no-build src/Dodo.Tracker.ComponentTests
-
с помощью
allurectl upload
.Upload
— это отдельный шаг в скрипте, в котором нужно указать путь до результатов.
Указывать необходимо путь до папки с результатами, например, bin/allure-result Вот тут я делал неправильно и использовал путь bin/ с уверенностью в том, что allurectl upload найдёт папку allure-result и загрузит оттуда все данные. Это не так. Он загрузит в облако всё, что найдёт в директории bin/ (dll-ки, результаты тестов, exe-файлы). В облаке уже происходит фильтрация, остаётся только то, что нужно, ненужное удаляется. Но с таким подходом увеличивается время загрузки, что в свою очередь увеличивает время прохождения тестов. А мы этого не хотим.- name: Upload allure results if: ${{ always() && steps.run-backend-component-tests.outcome != 'skipped' }} run: allurectl upload --launch-name "${{ env.ALLURE_LAUNCH_NAME }}" --launch-tags "${{ env.ALLURE_LAUNCH_TAGS }}" src/Dodo.Tracker.ComponentTests/bin/allure-results
Если выбирать из двух вариантов, то
watch
не такой гибкий. Если все тесты проходят, но по какой-то причине упадёт загрузка результатов (например, из-за проблем в Allure), то при использованииwatch
наш билд упадёт. Но упавший Allure — это не повод фейлить билд. Поэтомуupload
в этом отношении гибче, он выполняется как отдельный шаг и все остальные шаги можно продолжить выполнять, даже если шаг с загрузкой результатов не выполнился. Ноupload
увеличивает время прохождения тестов и всего пайплайна. Чем больше тестов, тем больше результатов ,тем больше времени займёт их загрузка.В общем, в зависимости от того что нам важнее — гибкость или скорость — можно использовать либо
allurectl watch
, либоallurectl upload
. Мы в разных сервисах используем разные команды.
Мы ещё добавляли шаг для отображения ссылки на запуск прямо в GitHub, чтобы не нужно было искать конкретный прогон в Allure и можно было по прямой ссылке могли перейти к запуску. Может выглядеть примерно так:
- name: Get launch url
if: ${{ always() && steps.run-backend-component-tests.outcome != 'skipped'}}
run: |
export $(allurectl job-run env | grep ALLURE_LAUNCH_URL)
echo "### [Test results](http://${ALLURE_LAUNCH_URL:8})" >> $GITHUB_STEP_SUMMARY
Запускаем тесты и получаем результаты
Собственно, делаем пуш в репу и запускаем тесты.
Что получилось
Всё получилось, теперь все автотесты генерируют тест-кейсы и складывают их в TestOps. А мы наслаждаемся свободным временем, ведь больше не нужно поддерживать автоматизированные тест-кейсы. Осталось автоматизацию довести до 100% и нас уволят (шутка).
Если серьёзно, то мы подключили 23 сервиса, в которых есть тесты. В 15 из них мы разметили в тестах шаги, и теперь там автоматически генерируются тест-кейсы.
Максимальное количество тестов в одном сервисе — 19751, а минимальное — 2.
Максимальное количество запусков в одном сервисе — 23046, а минимальное — 13.
Что не получилось
Я прикрутил Allure к юнит-тестам в своих проектах, но спустя 2 месяца выпилили обратно. Потому что юнит-тесты не флакуют, нам не нужно видеть историю их прогона. А размечать юнит-тесты в БДД-стиле, как советуют авторы BDD in action, я ещё не готов. Хотя идея в целом интересная, если нужно экстремальное понимание, что у нас проверяется.
Ещё мы столкнулись с проблемой, что если перезапустить билд с упавшими тестами (именно re-run сделать), то результаты предыдущего запуска перетрутся. Пока не знаем, что с этим делать.
Если у вас используется не NUnut, а xUnit, то важно знать, что Allure xUnit не работает нормально с параметризированными тестами, если в параметрах что-то отличное от строки. Есть пару вариантов решения - перейти как мы на NUnit, убрать такие тесты, либо пофиксить это и законтрибьютить в проект. В одном из проектов я выбрал мигрировать с xUnit на NUnit.
Пока непонятно, как вообще реализовать подход «тест-кейсы как код», чтобы ручные тест-кейсы тоже лежали рядом с кодом. Если кто-то уже реализовывал, напишите в комментариях или мне в Телеграм — очень интересно как это можно осуществить.
Кроме Хабра я пишу в телеграм-канал QAжется работает, подписывайтесь. Там я недавно рассказывал про четыре изменения, которые мы сделали в опенсорсном Allure.