Introducción a Allure Framework

Allure Framework es una herramienta de reportes de pruebas de código abierto que transforma los resultados de ejecución de tests en reportes HTML interactivos y visualmente atractivos. A diferencia de los reportes estándar que simplemente muestran el estado aprobado/fallido, Allure proporciona información detallada sobre la ejecución de pruebas, tendencias históricas, categorización y adjuntos personalizados que hacen que la depuración sea más rápida y los reportes más profesionales.

¿Por Qué Elegir Allure?

Los reportes de pruebas tradicionales a menudo carecen de la profundidad necesaria para una depuración efectiva y comunicación con stakeholders. Allure aborda estas limitaciones ofreciendo:

  • Visualizaciones ricas con gráficos, diagramas y líneas de tiempo
  • Historial detallado de ejecución para rastrear tendencias a lo largo del tiempo
  • Adjuntos personalizados incluyendo capturas de pantalla, logs y videos
  • Categorización y etiquetado para mejor organización de pruebas
  • Integración con frameworks de testing populares

Frameworks de Testing Soportados

Allure se integra perfectamente con los principales frameworks de testing en diferentes lenguajes de programación:

FrameworkLenguajeMétodo de Integración
PytestPythonAdaptador allure-pytest
JUnit 4/5JavaAdaptador allure-junit4/5
TestNGJavaAdaptador allure-testng
CucumberJava/RubyAdaptador allure-cucumber
JestJavaScriptAdaptador jest-allure
MochaJavaScriptAdaptador allure-mocha
NUnitC#Adaptador allure-nunit
PHPUnitPHPAdaptador allure-phpunit

Comenzando con Allure

Instalación y Configuración

Para Python con Pytest:

pip install allure-pytest

Para Java con Maven (JUnit 5):

<dependency>
    <groupId>io.qameta.allure</groupId>
    <artifactId>allure-junit5</artifactId>
 (como se discute en [REST Assured: Java-Based API Testing Framework for Modern Applications](/blog/rest-assured-api-testing))    <version>2.24.0</version>
    <scope>test</scope>
</dependency>

Para Java con Gradle (TestNG):

dependencies {
    testImplementation 'io.qameta.allure:allure-testng (como se discute en [TestNG vs JUnit 5: Complete Comparison for Java Testers](/blog/testng-vs-junit5)):2.24.0'
}

Herramienta de Línea de Comandos de Allure

Para generar y ver reportes, instala la herramienta de línea de comandos de Allure:

# macOS
brew install allure

# Windows (usando Scoop)
scoop install allure

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

Integración Profunda con Pytest

Configuración Básica

Crea un archivo pytest.ini en la raíz de tu proyecto:

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

Escribiendo Tests con Decoradores de Allure

import allure
import pytest

@allure.epic("Plataforma E-Commerce")
@allure.feature("Carrito de Compras")
@allure.story("Agregar Artículos al Carrito")
@allure.severity(allure.severity_level.CRITICAL)
def test_add_item_to_cart():
    with allure.step("Abrir página de producto"):
        product_page = open_product_page("laptop-123")

    with allure.step("Hacer clic en botón 'Agregar al Carrito'"):
        product_page.click_add_to_cart()

    with allure.step("Verificar que el artículo aparece en el carrito"):
        cart = open_cart()
        assert cart.item_count() == 1
        assert "laptop-123" in cart.get_items()

@allure.title("Login con credenciales válidas")
@allure.description("""
Este test verifica que los usuarios pueden iniciar sesión
exitosamente con una combinación válida de usuario y contraseña.
""")
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()

Adjuntos Personalizados

import allure
from selenium import webdriver

def test_screenshot_on_failure():
    driver = webdriver.Chrome()
    try:
        driver.get("https://example.com")
        # Lógica del test aquí
        assert False  # Simular fallo
    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
    )

Integración con JUnit 5

Configuración 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>

Ejemplo de Test Anotado

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

@Epic("Gestión de Usuarios")
@Feature("Registro de Usuario")
public class UserRegistrationTest {

    @Test
    @Story("Registrar nuevo usuario con datos válidos")
    @Severity(SeverityLevel.BLOCKER)
    @Description("Verificar que nuevos usuarios pueden registrarse con credenciales válidas")
    public void testUserRegistration() {
        step("Navegar a página de registro", () -> {
            // Lógica de navegación
        });

        step("Llenar formulario de registro", () -> {
            // Lógica de llenado de formulario
        });

        step("Enviar formulario y verificar éxito", () -> {
            // Envío y verificación
        });
    }

    @Step("Abrir aplicación en {url}")
    public void openApp(String url) {
        // Implementación
    }

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

Integración con TestNG

Configuración XML de 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>

Ejemplo de Test con TestNG

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

public class CheckoutTest {

    @Test
    @Epic("E-Commerce")
    @Feature("Proceso de Checkout")
    @Story("Completar compra")
    @Severity(SeverityLevel.CRITICAL)
    @Description("Verificar flujo completo de checkout desde carrito hasta confirmación de orden")
    public void testCompletePurchase() {
        addItemToCart("product-123");
        proceedToCheckout();
        fillShippingDetails();
        selectPaymentMethod();
        confirmOrder();
        verifyOrderConfirmation();
    }

    @Step("Agregar artículo {productId} al carrito")
    private void addItemToCart(String productId) {
        // Implementación
    }
}

Características Avanzadas

Tendencias Históricas

Allure mantiene el historial de ejecución de pruebas para mostrar tendencias a lo largo del tiempo. Configura el historial copiando resultados anteriores:

# Generar reporte actual
allure generate allure-results --clean -o allure-report

# Copiar historial para tendencias
cp -r allure-report/history allure-results/history

# Regenerar con historial
allure generate allure-results --clean -o allure-report

Configuración de Categorías

Crea categories.json en el directorio allure-results:

[
  {
    "name": "Defectos de Producto",
    "matchedStatuses": ["failed"],
    "messageRegex": ".*AssertionError.*"
  },
  {
    "name": "Problemas de Test",
    "matchedStatuses": ["broken"],
    "messageRegex": ".*NullPointerException.*"
  },
  {
    "name": "Tests Inestables",
    "matchedStatuses": ["passed", "failed"],
    "messageRegex": ".*timeout.*"
  }
]

Información de Ambiente

Crea environment.properties:

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

Integración con CI/CD

Pipeline de 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: Tests con Allure

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3

      - name: Configurar Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.11'

      - name: Instalar dependencias
        run: |
          pip install -r requirements.txt
          pip install allure-pytest

      - name: Ejecutar tests
        run: pytest --alluredir=./allure-results

      - name: Obtener historial de Allure
        uses: actions/checkout@v3
        if: always()
        continue-on-error: true
        with:
          ref: gh-pages
          path: gh-pages

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

      - name: Desplegar a GitHub Pages
        if: always()
        uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_branch: gh-pages
          publish_dir: allure-history

Mejores Prácticas

1. Descripciones de Pasos Significativas

# Mal
with allure.step("Paso 1"):
    do_something()

# Bien
with allure.step("Login con usuario 'testuser' y verificar carga del dashboard"):
    login("testuser", "password")
    assert_dashboard_visible()

2. Adjuntar Capturas Solo en Fallos

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. Organizar con Epics, Features y Stories

@allure.epic("Portal de Clientes")
@allure.feature("Autenticación")
@allure.story("Reseteo de Contraseña")
def test_password_reset():
    # Implementación del test

4. Usar Parámetros para Tests Data-Driven

@pytest.mark.parametrize("username,password", [
    ("user1", "pass1"),
    ("user2", "pass2"),
])
def test_login(username, password):
    allure.dynamic.title(f"Test de login para {username}")
    allure.dynamic.parameter("username", username)
    # Lógica del test

Conclusión

Allure Framework eleva los reportes de pruebas de simples logs de aprobado/fallido a documentación completa e interactiva. Su soporte para múltiples frameworks, capacidades de visualización ricas e integración con CI/CD lo convierten en una herramienta esencial para equipos de QA modernos. Al implementar las características de Allure—desde anotaciones básicas hasta tendencias históricas avanzadas—los equipos obtienen conocimientos más profundos sobre la calidad de las pruebas, haciendo la depuración más rápida y la comunicación con stakeholders más efectiva.

Comienza con la integración básica, agrega gradualmente adjuntos personalizados y categorización, luego aprovecha los datos históricos y la integración CI/CD para obtener el máximo valor.