Allure-отчёты для Playwright и pytest: что включить, что не превратить в свалку
Allure — самый популярный репортер в мире автотестов на пост-советском пространстве. На Stack Overflow по нему вопросов в три раза больше, чем по аналогам. На моих проектах он стоит везде, где гоняются Playwright и pytest. Не потому, что это лучший инструмент в мире, а потому, что разрыв между «дефолтным репортом» и Allure-дашбордом — пропасть.
Покажу, как поднять Allure для двух стеков, какие практики реально полезны на длинной дистанции, и где Allure начинает раздражать.
Зачем нужен Allure поверх дефолта
Дефолтный репорт Playwright показывает, какие тесты упали и трейс к ним. Дефолтный репорт pytest — список с зелёными точками и красными буквами F. Этого хватает, пока тестов меньше пятидесяти и команда из двух человек.
Когда тестов 500+, нужны:
- Группировка по фичам, эпикам, юзер-стори.
- История прогонов (тренд flaky-rate, тренд длительности).
- Шаги внутри теста с длительностью каждого.
- Прикреплённые скриншоты, логи, network-ответы.
- Категоризация падений (продукт-баг, тестовый баг, инфраструктура).
Allure всё это умеет. Главное — не превратить отчёт в чёрный ящик с тремя сотнями скриншотов «на всякий случай».
Allure для Playwright
Установка и подключение:
npm i -D allure-playwright
// playwright.config.ts
import { defineConfig } from '@playwright/test';
export default defineConfig({
reporter: [
['list'],
['allure-playwright', {
detail: true,
outputFolder: 'allure-results',
suiteTitle: false,
}],
],
});
После прогона:
npx allure generate allure-results -o allure-report --clean
npx allure open allure-report
В тестах используй декораторы для метаданных:
import { test, expect } from '@playwright/test';
import { allure } from 'allure-playwright';
test('пользователь сохраняет черновик', async ({ page }) => {
await allure.epic('Editor');
await allure.feature('Drafts');
await allure.story('Auto-save');
await allure.severity('critical');
await allure.tms('PROJ-1234');
await test.step('открыть редактор', async () => {
await page.goto('/editor');
});
await test.step('ввести 100 символов', async () => {
await page.getByRole('textbox').fill('a'.repeat(100));
});
await test.step('подождать автосохранения', async () => {
await expect(page.getByRole('status', { name: /сохранено/i })).toBeVisible();
});
});
test.step в Playwright виден в Allure как раскрывающийся блок с длительностью. На длинных тестах это бесценно: сразу видно, на каком шаге упало и сколько занимал каждый.
Allure для pytest
pip install allure-pytest
pytest --alluredir=allure-results
allure generate allure-results -o allure-report --clean
allure open allure-report
В pytest декораторы выглядят так:
import allure
import pytest
@allure.epic("Orders")
@allure.feature("Checkout")
@allure.story("Promo codes")
@allure.severity(allure.severity_level.CRITICAL)
@allure.tag("smoke")
def test_apply_valid_promo(client):
with allure.step("Создать корзину"):
cart = client.post("/carts").json()
with allure.step("Применить промокод"):
response = client.post(f"/carts/{cart['id']}/promo", json={"code": "WELCOME10"})
assert response.status_code == 200
with allure.step("Проверить итоговую сумму"):
cart_after = client.get(f"/carts/{cart['id']}").json()
allure.attach(str(cart_after), "cart state", allure.attachment_type.JSON)
assert cart_after["total"] == 90.00
allure.attach прикрепляет к шагу любые данные — JSON-ответ, скриншот, текстовый лог. На разборе падения это спасает: видно тело ответа сервера, не нужно лезть в логи бекенда.
История и тренды
Главная фича, ради которой ставят Allure — это история. После каждого прогона нужно копировать allure-report/history из предыдущего отчёта в новый allure-results/history. Тогда на дашборде появятся графики flaky-rate, длительности тестов, общего количества за период.
В CI это выглядит так:
- name: Restore Allure history
uses: actions/cache@v4
with:
path: allure-history
key: allure-history-${{ github.run_id }}
restore-keys: allure-history-
- name: Run tests
run: pytest --alluredir=allure-results
- name: Copy history
run: cp -r allure-history/* allure-results/history/ || true
- name: Generate report
run: |
allure generate allure-results -o allure-report --clean
cp -r allure-report/history allure-history
- name: Publish
uses: peaceiris/actions-gh-pages@v3
with:
publish_dir: allure-report
Без копирования истории Allure показывает каждый прогон «в вакууме», и весь смысл графиков пропадает. Это первое, что забывают сделать в первый раз.
Категоризация падений
По дефолту все падения у Allure лежат в одной куче «failed». Через файл categories.json в allure-results их можно делить на типы:
[
{
"name": "Network errors",
"matchedStatuses": ["broken"],
"messageRegex": ".*ECONNREFUSED.*|.*ETIMEDOUT.*"
},
{
"name": "Element not found",
"matchedStatuses": ["failed"],
"messageRegex": ".*locator.*resolved to 0 elements.*"
},
{
"name": "API 5xx",
"matchedStatuses": ["failed"],
"messageRegex": ".*status code 5\\d\\d.*"
}
]
На дашборде эти категории становятся отдельными группами. На разборе падений сразу видно — это сетевая проблема инфраструктуры или баг в продукте.
Что попробовала и не зашло
- Прикреплять скриншот к каждому шагу. Размер артефакта взрывается, время генерации репорта растёт, искать падение становится сложнее. Скриншот — только on-failure и в ключевых шагах.
- Прикреплять полный HTML страницы при падении. 2 МБ × 30 падений = 60 МБ репорта. На больших наборах артефакт взлетает в гигабайты. Лучше Playwright trace.zip — он компактнее и информативнее.
- Декораторы
@allure.titleс динамическим текстом из параметризации. На больших наборах теряется группировка: «Test for user user-1», «Test for user user-2» воспринимаются как разные тесты, хотя это один сценарий с разными данными. Лучше одинtitle, параметры — отдельным шагом. - «Все тесты имеют epic/feature/story». На onboarding кажется логично, через полгода мейтенанс декораторов стоит дороже их пользы. Использую только для сложных доменов с десятками фич, на простых — обычные имена тестов.
Где Allure раздражает
Не идеален. Список претензий за пять лет работы:
- Java под капотом. Генерация репорта тяжёлая, на больших наборах (10 000+ тестов) занимает минуты. На крупных проектах приходится разделять прогоны и собирать репорт частями.
- Слабая интеграция с CI на новых билдерах. Хорошие плагины есть для Jenkins, для GitHub Actions всё пилишь руками.
- Нет нормальной inline-версии без сервера. Открывать
index.htmlчерезfile://ломается из-за CORS. Нужен либоallure open, либо публикация на хостинг. - API между мажорными версиями ломается. С Allure 2 на Allure 3 переход требовал перепрошивки всех проектов.
Чек-лист: Allure без боли
- Подключи
allure-playwrightилиallure-pytest, не пиши свой репортер. - Используй
test.stepв Playwright иwith allure.step()в pytest для разбиения сценария. - Декораторы
epic/feature/story— только если у тебя есть реальная иерархия. На простых проектах — пропусти. - Скриншоты и логи — on-failure, не на каждый шаг.
- Обязательно настрой копирование истории в CI.
- Заведи
categories.jsonдля типизации падений. - Публикуй репорт на gh-pages или внутренний хостинг — не пытайся открыть локально через file://.
Allure не делает тесты лучше, но делает их видимыми для команды. На утреннем дейли можно открыть дашборд и за минуту понять, что вчерашний прогон дал, какие тесты в карантине, какие фичи покрашены. Без такого инструмента эти разговоры превращаются в «по моим ощущениям всё ок», что одинаково плохо и для QA-инженера, и для продукта.