Official Allure Framework libraries for generating Allure Report results in Rust.
- Learn more about Allure Report at https://allurereport.org
- 📚 Documentation – discover official documentation for Allure Report
- ❓ Questions and Support – get help from the team and community
- 📢 Official annoucements – be in touch with the latest updates
- 💬 General Discussion – engage in casual conversations, share insights and ideas with the community
allure-rust is the Rust implementation of the Allure Framework. It provides primitives to build
Allure-compatible results and a ready-to-use integration for cargo test.
This workspace currently includes:
allure-rust-commons: core runtime model, lifecycle, writer, and facade APIs.allure-reqwest:reqwestintegration for Allure HTTP Exchange attachments.allure-cargotest: test integration helper and reporter forcargo test.allure-test-macros: procedural macro crate that provides#[allure_test],#[step], and#[log_asserts].
For regular Rust tests with automatic lifecycle wiring:
cargo add allure-cargotest --devFor building your own integration/framework adapter:
cargo add allure-rust-commonsBy default, results are written to target/allure-results.
You can override it with:
ALLURE_RESULTS_DIR=./allure-results cargo testAfter tests finish and *-result.json files are present in your results directory,
use the Allure 3 CLI to generate and open the report:
allure generate ./target/allure-results --output ./target/allure-report --clean
allure open ./target/allure-reportIf you installed Allure 3 through Node tooling, use the equivalent
npxcommand provided by your installation method.
- Rust: stable toolchain (workspace uses Rust 2021 edition).
- OS: cross-platform by design (file-system based output, no OS-specific APIs).
- CI coverage in this repository currently runs on
ubuntu-latest.
Implemented runtime facade APIs include:
- Test lifecycle:
start_test_case,stop_test_case(plus compatibility aliasesstart_test,start_test_with_full_name,end_test) - Descriptions:
description,description_html - Labels and identity:
label,labels,epic,feature,story,suite,parent_suite,sub_suite,owner,severity,layer,tag,tags,id,allure_id,display_name,history_id,test_case_id - Links:
link,links,issue,tms - Parameters:
parameter,parameter_excluded,parameter_mode,parameter_with_options - Attachments:
attachment,attachment_path,attach_trace, and global diagnostics helpers - HTTP exchanges:
HttpExchangein commons, plusallure-reqwestforreqwestclients. Runtime helpers wrap exchanges as ordered evidence steps by default; exact-owner helpers live inallure_rust_commons::reporterfor reporter/adapter internals. - Steps and stages:
log_step,log_step_with,step,stage,#[step] - Assertion logging:
assert!,assert_eq!, and related standard assertion steps are logged by default and can be disabled withlog_assertsconfiguration
use allure_cargotest::{allure_test, step};
use allure_rust_commons::{feature, log_step, parameter, stage};
#[allure_test]
#[test]
fn test_with_allure() {
feature("Authentication");
parameter("browser", "firefox");
stage("open login page");
open_login_page();
log_step("login page opened");
}
#[step]
fn open_login_page() {
// your step implementation
}The #[allure_test] attribute initializes a reporter automatically (using
ALLURE_RESULTS_DIR or target/allure-results) and wraps the test lifecycle.
It supports ordinary () tests and explicit return types that implement
std::process::Termination, including Rust-style Result<(), E>, ExitCode, and custom
termination types. Returned Err values and unsuccessful ExitCode values are written to Allure
before Cargo interprets the result.
For environments where attribute macros are not allowed, use the macro-free runtime from commons:
use allure_rust_commons as allure;
#[test]
fn test_with_allure_runtime() {
allure::test(|| {
allure::feature("Authentication");
allure::stage("open login page");
allure::log_step("open login page");
});
}Async tests can compose #[allure_test] with a runtime-specific test macro such as
#[tokio::test]. Add and configure Tokio in your test crate; allure-cargotest does not depend
on Tokio.
use allure_cargotest::allure_test;
#[allure_test]
#[tokio::test]
async fn async_test_with_allure() {
allure.feature("Async API");
tokio::task::yield_now().await;
allure.parameter("runtime", "tokio");
}Allure context is available in the root async test body and awaited helpers. Implicit propagation
into independently spawned tasks is not guaranteed.
Async tests may also return Result<(), E>, ExitCode, custom Termination, or
impl Termination values when the runtime-specific test macro supports them.
#[allure_test] also derives synthetic suite labels from the Rust module path when a full
name is available. A single module segment becomes suite; with two or more segments, the first
becomes parentSuite, the second becomes suite, and any remaining module segments are joined
into subSuite. If your test calls allure.parent_suite(...), allure.suite(...), or
allure.sub_suite(...), those explicit labels override the synthetic defaults for the same label
name.
allure-rust-commons is the foundation layer that other integrations build on.
It exports these main building blocks:
- Model (
model): Allure data structures (TestResult,StepResult, labels, links, parameters, attachments, statuses). - Lifecycle (
lifecycle):AllureRuntime: owns a results writer and creates per-execution lifecycles.AllureLifecycle: manages active test state, nested steps, metadata, and final write.
- Writer (
writer):FileSystemResultsWriter: writes result JSON and attachment files into an output directory.
- Facade (
facade):AllureFacade: ergonomic API for tests/framework adapters.- Macro-free test runners such as
test,test_named, andtest_with. - Thread-bound helpers such as
feature,parameter,log_step,attachment, andstep. - global
allure()accessor backed byOnceLock.
- Config (
config):global_config(): process-wide env/runtime settings loaded once.- Cargo metadata config cached per manifest directory.
This separation lets you choose either:
- A high-level API (
AllureFacade) for minimal integration effort. - A low-level API (
AllureLifecycle+ model) for custom control.
To integrate Allure with another Rust test runner or framework:
- Initialize a writer and runtime once per process (or execution session).
- Create a lifecycle for test execution scope.
- Wrap framework hooks/events:
- on test start ->
start_test_case(...) - during test -> labels/links/parameters/steps/attachments
- on test end ->
stop_test_case(status, details)
- on test start ->
- Map framework statuses to Allure statuses (
Passed,Failed,Broken,Skipped). - Persist artifacts via
add_attachment(...)when your framework emits logs/files.
Minimal sketch:
use allure_rust_commons::{AllureRuntime, FileSystemResultsWriter, Status};
let writer = FileSystemResultsWriter::new("target/allure-results")?;
let runtime = AllureRuntime::new(writer);
let lifecycle = runtime.lifecycle();
lifecycle.start_test_case(
allure_rust_commons::StartTestCaseParams::new("my test").with_full_name("suite::my test")
);
// ... update metadata, steps, and attachments during execution ...
lifecycle.stop_test_case(Status::Passed, None);For convenience APIs, wrap the lifecycle in AllureFacade::with_lifecycle(...) and expose
framework-specific helpers similar to #[allure_test] from allure-cargotest. Adapters can also
call push_current_allure(&facade) while a test runs so users can import thread-bound functions
directly from allure-rust-commons.
Rust requires attribute procedural macros to be compiled from a proc-macro crate.
A proc-macro crate cannot serve as a regular runtime library crate at the same
time, so runtime/reporter APIs stay in allure-cargotest and macro implementation
lives in allure-test-macros.
From a user perspective this remains a single entrypoint because
allure-cargotest re-exports #[allure_test], #[step], and #[log_asserts].