Install
openclaw skills install rust-testing-code-reviewReviews Rust test code for unit test patterns, integration test structure, async testing, mocking approaches, and property-based testing. Covers Rust 2024 edition changes including async fn in traits for mocks,
openclaw skills install rust-testing-code-reviewCargo.toml (2021 vs 2024). Edition 2024 changes temporary scoping in if let and tail expressions, and makes #[expect] the preferred lint suppression#[cfg(test)] modules, integration tests in tests/ directory#[tokio::test] for async tests, proper runtime configuration. Check for async-trait on mocks that could use native async fn in traitsif let assertions for edition 2024 temporary scope changesLazyLock over lazy_static!/once_cell for shared fixturesDo not advance to Output Format until each pass condition is satisfied (yes/no with a concrete artifact).
Cargo.toml (or workspace [workspace.package] / inherited edition) and note the edition value. Pass: you can quote edition = "…" (or document “inherited from workspace”) before citing Rust 2024–specific behavior (if let / tail temporary drops, #[expect] vs #[allow] migration, native async fn in traits as default). If edition is not 2024, do not report those items as edition-2024 regressions; at most Informational if still useful.dyn vs static async mocks — Before suggesting native async fn in traits instead of async-trait, check whether the mock is used as dyn Trait. Pass: if dyn is required, you either skip that suggestion or align with Valid Patterns (async-trait still needed).beagle-rust:review-verification-protocol are done before any finding is listed (see Before Submitting Findings).Report findings as:
[FILE:LINE] ISSUE_TITLE
Severity: Critical | Major | Minor | Informational
Description of the issue and why it matters.
| Issue Type | Reference |
|---|---|
Unit tests, assertions, naming, snapshots, rstest, doc tests, #[expect], LazyLock fixtures, tail expression scope | references/unit-tests.md |
Integration tests, async testing, fixtures, test databases, native async fn mocks, if let temporary scope | references/integration-tests.md |
Fuzzing, proptest, Miri, Loom basics, mocking strategies, stub/fake/mock/spy taxonomy, rstest matrix, paste!, build.rs test gen, criterion baselines + black_box discipline, trybuild UI tests, clippy lint groups | references/advanced-testing.md |
| Loom interleaving tests, Miri UB checks, shuttle, ThreadSanitizer, CI matrix for concurrent code | references/concurrency-testing.md |
#[cfg(test)] mod tests within source filestests/ directory (one file per module or feature)use super::* in test modules to access parent module itemstest_<function>_<scenario>_<expected>#[tokio::test] used for async test functions#[tokio::test(flavor = "multi_thread")] when testing multi-threaded behaviorblock_on inside async tests (use .await directly)async fn instead of async-trait crate (stable since Rust 1.75)assert_eq! / assert_ne! used for value comparisons (better error messages than assert!)matches! macro used for enum variant checkingmatches! or pattern matching, not string comparisonif let assertions reviewed for edition 2024 temporary scope — temporaries in conditions drop earlier, may invalidate borrowsstd::sync::LazyLock used for shared test fixtures instead of lazy_static! or once_cell (stable since Rust 1.80)Result::Err variants tested, not just happy paths#[should_panic] used sparingly — prefer Result-returning tests#[expect(lint)] used instead of #[allow(lint)] for test-specific suppressions (stable since Rust 1.81)#[expect] or #[allow] in test code#[allow] attributes migrated to #[expect] for self-cleaning behaviortest_happy_path)mod blocks for organization<function>_should_<behavior>_when_<condition>cargo insta used for complex structural output (JSON, YAML, HTML, CLI output)snapshots/ directoryassert_eq!, not snapshotsrstest used to avoid duplicated test functions for similar inputs#[rstest] with #[case::name] attributes for descriptive parametrized tests#[fixture] used for shared test setup when multiple tests need same construction#[case(1)])#[rstest] #[tokio::test] for async parametrized tests/// # Examples with runnable code# to keep examples cleancargo test --doc passes (nextest doesn't run doc tests)Detailed guidance: references/concurrency-testing.md
unsafe impl Send|Sync / state machines have a #[cfg(loom)] test using loom::sync and loom::thread shims (not std::sync)unsafe touching atomics, pointers, or UnsafeCell run cargo +nightly miri test --all-features in CI on every PR (not release-only, not module-level cfg_attr(miri, ignore))AtomicPtr stacks/queues/lists) have loom + Miri (Stacked Borrows and Tree Borrows) + proptest-driven operation sequencesInstant::now, rand, env, HashMap iteration) are kept out of loom::model bodies--release with a LOOM_MAX_PREEMPTIONS bound; loom tests live in a separate tests/ file so --cfg loom does not poison normal cargo testnextest run -j1 is not cited as evidence of race-condition coverage; FFI-heavy unsafe extern "C" paths have a ThreadSanitizer jobDetailed guidance: references/advanced-testing.md
mockall-style mocks are not used where a fake would be simpler (in-memory DB beats expectation-heavy mocks for repository-style traits)Detailed guidance: references/advanced-testing.md
criterion::black_box(...) to prevent constant-folding; pointer-flavored inputs use black_box(input.as_ptr()) not black_box(&input)iter_batched setup closure, NOT inside the measured closurecargo bench -- --save-baseline main; feature branches compare with --baseline main; regression threshold defined and enforced--profile bench (release optimization + debug symbols for flamegraph correlation)#[bench] (unstable, deprecated) — use criterion exclusivelyDetailed guidance: references/advanced-testing.md
rstest with #[case::name(...)] (descriptive case names in test output)rstest with #[values(...)] on multiple parameters (Cartesian product), not hand-expanded test functionspaste! macro or build.rs codegen (one #[test] fn per file/case)Detailed guidance: references/advanced-testing.md
trybuild::TestCases covering each failure path with a .stderr reference.stderr outputs were regenerated after the latest rustc bump (otherwise spurious CI failures); TRYBUILD=overwrite cargo test is documented in CONTRIBUTING.stderr format shifts between stable releases)Detailed guidance: references/advanced-testing.md
clippy::correctness is deny (always — these are bugs)clippy::suspicious is warn or deny for librariesclippy::perf is warn (real wins on hot paths)clippy::pedantic enabled for libraries; suppressions use #[expect(clippy::lint_name, reason = "...")] with justification, not bare #[allow]clippy::nursery is NOT enabled in CI (experimental; changes between rustc releases)clippy::restriction lints are opt-in individually; the group is never enabled wholesale#[should_panic] without expected message (catches any panic, including wrong ones)unwrap() in test setup that hides the real failure locationif let with inline temporary in assertion that breaks under edition 2024 temporary scopingasync-trait on mock traits when native async fn in traits is available and project targets edition 2024assert!(x == y) instead of assert_eq!(x, y) (worse error messages)#[allow] used where #[expect] would provide self-cleaning suppressionlazy_static! or once_cell used for test fixtures when LazyLock is availableproptest or quickcheckunwrap() / expect() in tests — Panicking on unexpected errors is the correct test behavioruse super::* in test modules — Standard pattern for accessing parent items#[allow(dead_code)] on test helpers — Helper functions may not be used in every testclone() in tests — Clarity over performanceassert! for boolean checks — Fine when the expression is clearly boolean (.is_some(), .is_empty())unwrap() on Result-returning test functions — Propagating with ? is also fine but not requiredasync-trait on mock traits requiring dyn dispatch — Native async fn in traits doesn't support dyn Trait; async-trait is still needed there#[expect] with justification on test helpers — Self-cleaning lint suppression is correct in test codeLazyLock for expensive shared test fixtures — Thread-safe lazy init is appropriate for test globalsLoad and follow beagle-rust:review-verification-protocol before reporting any issue.