rvtest — A Next Level Testing Framework for Rust.
rvtest extends Rust's built-in testing capabilities with:
- BDD-style specs — organise tests with
describe/itblocks, nested hierarchies, tags, timeouts, and retries. - Property-based testing — verify invariants over randomly generated inputs, with automatic counterexample shrinking.
- Parametrized tests — run the same test logic against multiple inputs without boilerplate.
- Rich reporting — Pretty (human-readable with colour), TAP, JUnit XML, JSON, and Compact formats.
- Code coverage — measure line/function/region coverage via LLVM
instrumentation (
cargo rvtest --coverage). - Configurable runner — parallel execution, name and tag filtering, fail-fast, configurable timeouts and retries.
Usage inside #[test] (recommended)
Rvtest is designed to be used inside standard #[test] functions.
Build a spec with [describe] and it, call
run, then verify with assert_all_pass:
use rvtest::spec::describe;
#[test]
fn calculator_tests() {
describe("Calculator")
.it("adds two positive numbers", || {
assert_eq!(2 + 2, 4);
})
.it("subtracts", || {
assert_eq!(5 - 3, 2);
})
.tag("arithmetic")
.run()
.assert_all_pass();
}
If any spec fails, assert_all_pass will panic with a detailed report,
which causes the #[test] to fail naturally — no need for main().
Property-based testing inside #[test]
use rvtest::property::{check, any};
#[test]
fn addition_is_commutative() {
check("commutativity", any::<i32>(), |a: &i32| {
let b: i32 = 42; // fixed second operand
a + b == b + *a
});
}
Parametrized tests inside #[test]
use rvtest::param::parametrize;
#[test]
fn addition_cases() {
for case in parametrize("add", [(1, 1, 2), (0, 0, 0), (-1, 1, 0)], |(a, b, exp)| {
assert_eq!(a + b, *exp);
}) {
assert!(case.status.is_passed(), "{} failed", case.name);
}
}
CLI usage (cargo rvtest)
The cargo-rvtest binary runs specs defined in your project and
produces formatted output. See cargo rvtest --help.