Введение в Allure Framework

Allure Framework — это open-source инструмент для создания отчетов о тестировании, который преобразует результаты выполнения тестов в интерактивные, визуально привлекательные HTML-отчеты. В отличие от стандартных отчетов, которые просто показывают статус пройден/не пройден, Allure предоставляет детальную информацию о выполнении тестов, исторические тренды, категоризацию и пользовательские вложения, которые делают отладку быстрее, а отчетность — более профессиональной.

Почему Стоит Выбрать Allure?

Традиционные отчеты о тестировании часто не имеют глубины, необходимой для эффективной отладки и коммуникации со стейкхолдерами. Allure решает эти ограничения, предлагая:

  • Богатые визуализации с графиками, диаграммами и таймлайнами
  • Детальную историю выполнения тестов для отслеживания трендов во времени
  • Пользовательские вложения, включая скриншоты, логи и видео
  • Категоризацию и тегирование для лучшей организации тестов
  • Интеграцию с популярными фреймворками тестирования

Поддерживаемые Фреймворки Тестирования

Allure легко интегрируется с основными фреймворками тестирования на разных языках программирования:

ФреймворкЯзыкМетод Интеграции
PytestPythonАдаптер allure-pytest
JUnit 4/5JavaАдаптер allure-junit4/5
TestNGJavaАдаптер allure-testng
CucumberJava/RubyАдаптер allure-cucumber
JestJavaScriptАдаптер jest-allure
MochaJavaScriptАдаптер allure-mocha
NUnitC#Адаптер allure-nunit
PHPUnitPHPАдаптер allure-phpunit

Начало Работы с Allure

Установка и Настройка

Для Python с Pytest:

pip install allure-pytest

Для Java с Maven (JUnit 5):

<dependency>
    <groupId>io.qameta.allure</groupId>
    <artifactId>allure-junit5</artifactId>
 (как обсуждается в [REST Assured: Java-Based API Testing Framework for Modern Applications](/blog/rest-assured-api-testing))    <version>2.24.0</version>
    <scope>test</scope>
</dependency>

Для Java с Gradle (TestNG):

dependencies {
    testImplementation 'io.qameta.allure:allure-testng (как обсуждается в [TestNG vs JUnit 5: Complete Comparison for Java Testers](/blog/testng-vs-junit5)):2.24.0'
}

Инструмент Командной Строки Allure

Для генерации и просмотра отчетов установите инструмент командной строки Allure:

# macOS
brew install allure

# Windows (используя Scoop)
scoop install allure

# Linux
sudo apt-add-repository ppa:qameta/allure
sudo apt-get update
sudo apt-get install allure

Глубокая Интеграция с Pytest

Базовая Конфигурация

Создайте файл pytest.ini в корне вашего проекта:

[pytest]
addopts = --alluredir=./allure-results

Написание Тестов с Декораторами Allure

import allure
import pytest

@allure.epic("Платформа E-Commerce")
@allure.feature("Корзина Покупок")
@allure.story("Добавление Товаров в Корзину")
@allure.severity(allure.severity_level.CRITICAL)
def test_add_item_to_cart():
    with allure.step("Открыть страницу продукта"):
        product_page = open_product_page("laptop-123")

    with allure.step("Нажать кнопку 'Добавить в корзину'"):
        product_page.click_add_to_cart()

    with allure.step("Проверить, что товар появился в корзине"):
        cart = open_cart()
        assert cart.item_count() == 1
        assert "laptop-123" in cart.get_items()

@allure.title("Вход с валидными учетными данными")
@allure.description("""
Этот тест проверяет, что пользователи могут успешно войти
с валидной комбинацией имени пользователя и пароля.
""")
def test_valid_login():
    allure.attach("admin", name="username", attachment_type=allure.attachment_type.TEXT)
    login_page = LoginPage()
    login_page.login("admin", "password123")
    assert login_page.is_logged_in()

Пользовательские Вложения

import allure
from selenium import webdriver

def test_screenshot_on_failure():
    driver = webdriver.Chrome()
    try:
        driver.get("https://example.com")
        # Логика теста здесь
        assert False  # Симуляция ошибки
    except AssertionError:
        allure.attach(
            driver.get_screenshot_as_png(),
            name="failure_screenshot",
            attachment_type=allure.attachment_type.PNG
        )
        raise
    finally:
        driver.quit()

def test_attach_json_response():
    response = {"status": "success", "data": [1, 2, 3]}
    allure.attach(
        json.dumps(response, indent=2),
        name="api_response",
        attachment_type=allure.attachment_type.JSON
    )

Интеграция с JUnit 5

Конфигурация Maven

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.22.2</version>
            <configuration>
                <properties>
                    <property>
                        <name>listener</name>
                        <value>io.qameta.allure.junit5.AllureJunit5</value>
                    </property>
                </properties>
            </configuration>
        </plugin>
    </plugins>
</build>

Пример Аннотированного Теста

import io.qameta.allure.*;
import org.junit.jupiter.api.Test;

@Epic("Управление Пользователями")
@Feature("Регистрация Пользователя")
public class UserRegistrationTest {

    @Test
    @Story("Регистрация нового пользователя с валидными данными")
    @Severity(SeverityLevel.BLOCKER)
    @Description("Проверить, что новые пользователи могут зарегистрироваться с валидными учетными данными")
    public void testUserRegistration() {
        step("Перейти на страницу регистрации", () -> {
            // Логика навигации
        });

        step("Заполнить форму регистрации", () -> {
            // Логика заполнения формы
        });

        step("Отправить форму и проверить успех", () -> {
            // Отправка и проверка
        });
    }

    @Step("Открыть приложение по адресу {url}")
    public void openApp(String url) {
        // Реализация
    }

    @Attachment(value = "Request body", type = "application/json")
    public String attachJson(String json) {
        return json;
    }
}

Интеграция с TestNG

XML Конфигурация TestNG

<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd" >
<suite name="Allure TestNG Suite">
    <listeners>
        <listener class-name="io.qameta.allure.testng.AllureTestNg"/>
    </listeners>
    <test name="Regression Tests">
        <classes>
            <class name="com.example.tests.LoginTest"/>
            <class name="com.example.tests.CheckoutTest"/>
        </classes>
    </test>
</suite>

Пример Теста с TestNG

import io.qameta.allure.*;
import org.testng.annotations.Test;

public class CheckoutTest {

    @Test
    @Epic("E-Commerce")
    @Feature("Процесс Оформления Заказа")
    @Story("Завершение покупки")
    @Severity(SeverityLevel.CRITICAL)
    @Description("Проверить полный поток оформления заказа от корзины до подтверждения заказа")
    public void testCompletePurchase() {
        addItemToCart("product-123");
        proceedToCheckout();
        fillShippingDetails();
        selectPaymentMethod();
        confirmOrder();
        verifyOrderConfirmation();
    }

    @Step("Добавить товар {productId} в корзину")
    private void addItemToCart(String productId) {
        // Реализация
    }
}

Продвинутые Возможности

Исторические Тренды

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

# Сгенерировать текущий отчет
allure generate allure-results --clean -o allure-report

# Скопировать историю для трендов
cp -r allure-report/history allure-results/history

# Перегенерировать с историей
allure generate allure-results --clean -o allure-report

Конфигурация Категорий

Создайте categories.json в директории allure-results:

[
  {
    "name": "Дефекты Продукта",
    "matchedStatuses": ["failed"],
    "messageRegex": ".*AssertionError.*"
  },
  {
    "name": "Проблемы Тестов",
    "matchedStatuses": ["broken"],
    "messageRegex": ".*NullPointerException.*"
  },
  {
    "name": "Нестабильные Тесты",
    "matchedStatuses": ["passed", "failed"],
    "messageRegex": ".*timeout.*"
  }
]

Информация об Окружении

Создайте environment.properties:

Browser=Chrome
Browser.Version=119.0
Stand=Production
OS=macOS 14.0
Java.Version=17.0.8

Интеграция с CI/CD

Pipeline Jenkins

pipeline {
    agent any

    stages {
        stage('Test') {
            steps {
                sh 'mvn clean test'
            }
        }

        stage('Generate Allure Report') {
            steps {
                allure([
                    includeProperties: false,
                    jdk: '',
                    properties: [],
                    reportBuildPolicy: 'ALWAYS',
                    results: [[path: 'target/allure-results']]
                ])
            }
        }
    }
}

GitHub Actions

name: Тесты с Allure

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3

      - name: Настроить Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.11'

      - name: Установить зависимости
        run: |
          pip install -r requirements.txt
          pip install allure-pytest

      - name: Запустить тесты
        run: pytest --alluredir=./allure-results

      - name: Получить историю Allure
        uses: actions/checkout@v3
        if: always()
        continue-on-error: true
        with:
          ref: gh-pages
          path: gh-pages

      - name: Отчет Allure
        uses: simple-elf/allure-report-action@master
        if: always()
        with:
          allure_results: allure-results
          allure_history: allure-history
          keep_reports: 20

      - name: Развернуть на GitHub Pages
        if: always()
        uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_branch: gh-pages
          publish_dir: allure-history

Лучшие Практики

1. Осмысленные Описания Шагов

# Плохо
with allure.step("Шаг 1"):
    do_something()

# Хорошо
with allure.step("Вход с именем пользователя 'testuser' и проверка загрузки дашборда"):
    login("testuser", "password")
    assert_dashboard_visible()

2. Прикреплять Скриншоты Только при Ошибках

import pytest

@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
    outcome = yield
    rep = outcome.get_result()
    if rep.when == 'call' and rep.failed:
        driver = item.funcargs.get('driver')
        if driver:
            allure.attach(
                driver.get_screenshot_as_png(),
                name='screenshot',
                attachment_type=allure.attachment_type.PNG
            )

3. Организовывать с Помощью Epics, Features и Stories

@allure.epic("Портал Клиентов")
@allure.feature("Аутентификация")
@allure.story("Сброс Пароля")
def test_password_reset():
    # Реализация теста

4. Использовать Параметры для Data-Driven Тестов

@pytest.mark.parametrize("username,password", [
    ("user1", "pass1"),
    ("user2", "pass2"),
])
def test_login(username, password):
    allure.dynamic.title(f"Тест входа для {username}")
    allure.dynamic.parameter("username", username)
    # Логика теста

Заключение

Allure Framework поднимает отчеты о тестировании от простых логов пройден/не пройден до комплексной интерактивной документации. Его поддержка множества фреймворков, богатые возможности визуализации и интеграция с CI/CD делают его необходимым инструментом для современных QA-команд. Внедряя возможности Allure—от базовых аннотаций до продвинутых исторических трендов—команды получают более глубокое понимание качества тестов, делая отладку быстрее, а коммуникацию со стейкхолдерами более эффективной.

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