rvtest — A Next Level Testing Library for Rust.
rvtest extends Rust's built-in testing capabilities with:
- BDD-style specs — organise tests with
describe/itblocks, nested hierarchies, lifecycle hooks (before_all,after_all,before_each,after_each), 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.
- Assertion macros —
assert_eq!with structural diffs,assert_ok!,assert_err!,assert_matches!,assert_delta!. - Mocking utilities —
Spy(call-recording),Stub(fixed return),patch!(scoped function replacement). No proc-macro required. - Snapshot testing — file-based snapshot assertions with
--update-allauto-accept and--reviewinteractive mode. - Architecture tests — enforce module dependency rules
(
may_depend_on,may_not_depend_on,must_not_have_cycles,public_api_doc_required). - Output capture — per-test stdout/stderr capture, shown only on failure.
- Rich reporting — Pretty (human-readable with colour), TAP, JUnit XML, JSON, Compact, and GitHub Actions annotations formats.
- Code coverage — measure line/function/region coverage via
pure-Rust
.profrawparser (cargo rvtest --coverage). No external LLVM tools required. - Configurable runner — parallel execution, name and tag filtering, fail-fast, configurable timeouts and retries.
- Optional proc-macro API —
#[describe]/#[it]attribute macros via themacrosfeature.
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();
}
Tags let you selectively run tests: cargo rvtest --tag arithmetic.
Other modifiers include .timeout(dur) and .retries(n).
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;
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.