Introduction to Allure Framework
Allure Framework is an open-source test reporting tool that transforms test execution results into interactive, visually appealing HTML reports. Unlike standard test reports that simply show pass/fail status, Allure provides detailed insights into test execution, historical trends, categorization, and custom attachments that make debugging faster and reporting more professional.
Why Choose Allure?
Traditional test reports often lack the depth needed for effective debugging and stakeholder communication. Allure addresses these limitations by offering:
- Rich visualizations with charts, graphs, and timelines
- Detailed test execution history to track trends over time
- Custom attachments including screenshots, logs, and videos
- Categorization and tagging for better test organization
- Integration with popular testing frameworks
Supported Testing Frameworks
Allure integrates seamlessly with major testing frameworks across different programming languages:
Framework | Language | Integration Method |
---|---|---|
Pytest | Python | allure-pytest adapter |
JUnit 4/5 | Java | allure-junit4/5 adapter |
TestNG | Java | allure-testng adapter |
Cucumber | Java/Ruby | allure-cucumber adapter |
Jest | JavaScript | jest-allure adapter |
Mocha | JavaScript | allure-mocha adapter |
NUnit | C# | allure-nunit adapter |
PHPUnit | PHP | allure-phpunit adapter |
Getting Started with Allure
Installation and Setup
For Python with Pytest:
pip install allure-pytest
For Java with Maven (JUnit 5):
<dependency>
<groupId>io.qameta.allure</groupId>
<artifactId>allure-junit5</artifactId>
(as discussed in [REST Assured: Java-Based API Testing Framework for Modern Applications](/blog/rest-assured-api-testing)) <version>2.24.0</version>
<scope>test</scope>
</dependency>
For Java with Gradle (TestNG):
dependencies {
testImplementation 'io.qameta.allure:allure-testng (as discussed in [TestNG vs JUnit 5: Complete Comparison for Java Testers](/blog/testng-vs-junit5)):2.24.0'
}
Allure Command Line Tool
To generate and view reports, install the Allure command-line tool:
# macOS
brew install allure
# Windows (using Scoop)
scoop install allure
# Linux
sudo apt-add-repository ppa:qameta/allure
sudo apt-get update
sudo apt-get install allure
Pytest Integration Deep Dive
Basic Configuration
Create a pytest.ini
file in your project root:
[pytest]
addopts = --alluredir=./allure-results
Writing Tests with Allure Decorators
import allure
import pytest
@allure.epic("E-Commerce Platform")
@allure.feature("Shopping Cart")
@allure.story("Add Items to Cart")
@allure.severity(allure.severity_level.CRITICAL)
def test_add_item_to_cart():
with allure.step("Open product page"):
product_page = open_product_page("laptop-123")
with allure.step("Click 'Add to Cart' button"):
product_page.click_add_to_cart()
with allure.step("Verify item appears in cart"):
cart = open_cart()
assert cart.item_count() == 1
assert "laptop-123" in cart.get_items()
@allure.title("Login with valid credentials")
@allure.description("""
This test verifies that users can successfully login
with valid username and password combination.
""")
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()
Custom Attachments
import allure
from selenium import webdriver
def test_screenshot_on_failure():
driver = webdriver.Chrome()
try:
driver.get("https://example.com")
# Test logic here
assert False # Simulate failure
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 Integration
Maven Configuration
<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>
Annotated Test Example
import io.qameta.allure.*;
import org.junit.jupiter.api.Test;
@Epic("User Management")
@Feature("User Registration")
public class UserRegistrationTest {
@Test
@Story("Register new user with valid data")
@Severity(SeverityLevel.BLOCKER)
@Description("Verify that new users can register with valid credentials")
public void testUserRegistration() {
step("Navigate to registration page", () -> {
// Navigation logic
});
step("Fill registration form", () -> {
// Form filling logic
});
step("Submit form and verify success", () -> {
// Submission and verification
});
}
@Step("Open application at {url}")
public void openApp(String url) {
// Implementation
}
@Attachment(value = "Request body", type = "application/json")
public String attachJson(String json) {
return json;
}
}
TestNG Integration
TestNG XML Configuration
<!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 Test Example
import io.qameta.allure.*;
import org.testng.annotations.Test;
public class CheckoutTest {
@Test
@Epic("E-Commerce")
@Feature("Checkout Process")
@Story("Complete purchase")
@Severity(SeverityLevel.CRITICAL)
@Description("Verify complete checkout flow from cart to order confirmation")
public void testCompletePurchase() {
addItemToCart("product-123");
proceedToCheckout();
fillShippingDetails();
selectPaymentMethod();
confirmOrder();
verifyOrderConfirmation();
}
@Step("Add item {productId} to cart")
private void addItemToCart(String productId) {
// Implementation
}
}
Advanced Features
Historical Trends
Allure maintains test execution history to show trends over time. Configure history by copying previous results:
# Generate current report
allure generate allure-results --clean -o allure-report
# Copy history for trends
cp -r allure-report/history allure-results/history
# Regenerate with history
allure generate allure-results --clean -o allure-report
Categories Configuration
Create categories.json
in allure-results
directory:
[
{
"name": "Product Defects",
"matchedStatuses": ["failed"],
"messageRegex": ".*AssertionError.*"
},
{
"name": "Test Issues",
"matchedStatuses": ["broken"],
"messageRegex": ".*NullPointerException.*"
},
{
"name": "Flaky Tests",
"matchedStatuses": ["passed", "failed"],
"messageRegex": ".*timeout.*"
}
]
Environment Information
Create environment.properties
:
Browser=Chrome
Browser.Version=119.0
Stand=Production
OS=macOS 14.0
Java.Version=17.0.8
CI/CD Integration
Jenkins Pipeline
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 with Allure
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install dependencies
run: |
pip install -r requirements.txt
pip install allure-pytest
- name: Run tests
run: pytest --alluredir=./allure-results
- name: Get Allure history
uses: actions/checkout@v3
if: always()
continue-on-error: true
with:
ref: gh-pages
path: gh-pages
- name: Allure Report
uses: simple-elf/allure-report-action@master
if: always()
with:
allure_results: allure-results
allure_history: allure-history
keep_reports: 20
- name: Deploy to GitHub Pages
if: always()
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_branch: gh-pages
publish_dir: allure-history
Best Practices
1. Meaningful Step Descriptions
# Bad
with allure.step("Step 1"):
do_something()
# Good
with allure.step("Login with username 'testuser' and verify dashboard loads"):
login("testuser", "password")
assert_dashboard_visible()
2. Attach Screenshots Only on Failure
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. Organize with Epics, Features, and Stories
@allure.epic("Customer Portal")
@allure.feature("Authentication")
@allure.story("Password Reset")
def test_password_reset():
# Test implementation
4. Use Parameters for Data-Driven Tests
@pytest.mark.parametrize("username,password", [
("user1", "pass1"),
("user2", "pass2"),
])
def test_login(username, password):
allure.dynamic.title(f"Login test for {username}")
allure.dynamic.parameter("username", username)
# Test logic
Conclusion
Allure Framework elevates test reporting from simple pass/fail logs to comprehensive, interactive documentation. Its support for multiple frameworks, rich visualization capabilities, and CI/CD integration make it an essential tool for modern QA teams. By implementing Allure’s features—from basic annotations to advanced historical trends—teams gain deeper insights into test quality, making debugging faster and stakeholder communication more effective.
Start with basic integration, gradually add custom attachments and categorization, then leverage historical data and CI/CD integration for maximum value.