gor-cli 0.2.0

A Rust CLI for GitHub — a 'gh' clone
Documentation
# Research: Rust Testing, Benchmarking & Code Quality Best Practices (2025–2026)

## Summary
A thorough modern Rust testing strategy is layered: fast unit/integration/doctest coverage run by `cargo nextest`, snapshot tests (`insta`) for complex output, property-based tests (`proptest`) and fuzzing (`cargo-fuzz`/`cargo-afl`) for parsers and input handling, `criterion`/`divan` benchmarks for hot paths, and scheduled `cargo-mutants` mutation testing plus `cargo-llvm-cov` coverage to validate the suite itself. For a CLI tool specifically, this is anchored by a lib/binary split so logic is testable, `assert_cmd`/`assert_fs` integration tests against the real binary, and `clippy`/`fmt`/`audit`/`deny` gates in CI.

## Findings

### 1. Test organization
- **Unit tests** live in a `#[cfg(test)] mod tests` block inside source files and test private functions/isolated logic directly. **Integration tests** live in the top-level `tests/` directory, each compiled as a separate crate that can only reach your *public* API, verifying module interactions. **Doc tests** are code examples in `///` comments that `cargo test` compiles and runs, keeping docs honest. [Source: Rust Book — Test Organization](https://doc.rust-lang.org/stable/book/ch11-03-test-organization.html)
- **Snapshot testing** with [`insta`](https://docs.rs/insta/latest/insta/index.html) (latest `insta` 1.47.2 / `cargo-insta` 1.48.0, mid-2026) is the standard for large or frequently-changing outputs via `assert_snapshot!`/`assert_yaml_snapshot!`/`assert_json_snapshot!`, with review via `cargo insta review` or `INSTA_UPDATE`. Recent additions include `INSTA_PENDING_DIR` for hermetic (Bazel) builds and a (still unstable) `tokenstream` format for proc-macro AST nodes. [Source: insta docs](https://docs.rs/insta/latest/insta/index.html), [insta releases](https://github.com/mitsuhiko/insta)
- **`cargo nextest`** (0.9.136, May 2026) is the de-facto faster, more observable test runner — parallel execution, per-test timeouts, JUnit/TAP output, and filter expressions (`-E`) for grouping. Widely adopted in CI for large workspaces. [Source: cargo-nextest releases](https://github.com/nextest-rs/nextest/releases/tag/cargo-nextest-0.9.136), [JetBrains on nextest](https://blog.jetbrains.com/rust/2026/05/01/faster-rust-tests-with-cargo-nextest/)

### 2. Property-based testing
- **`proptest`** (inspired by Python Hypothesis) uses explicit, composable *strategy* objects, supporting multiple generators per type, richer constraints, and automatic shrinking; generally preferred for flexibility. **`quickcheck`** (BurntSushi) follows the Haskell model with one canonical type-driven generator, is faster and stateless in shrinking but less flexible for custom constraints. The official proptest docs recommend proptest when you need tailored/structured input generation. [Source: Proptest vs QuickCheck](https://proptest-rs.github.io/proptest/proptest/vs-quickcheck.html), [proptest repo](https://github.com/proptest-rs/proptest)
- Practical guidance: use property tests for parsers, serializers, and invariants (e.g., "round-trip encode/decode", "sort is stable and sorted"); reach for them where unit tests only sample a few inputs.

### 3. Fuzzing
- **`cargo-fuzz`** (libFuzzer-backed) and **`cargo-afl`** (AFL++-backed) are the two main options. Best practices: for memory-safe Rust, disable ASan with `--sanitizer none` for large speedups; use **structure-aware fuzzing** via the `Arbitrary` trait (or `fuzz_mutator!`) so the fuzzer generates valid-ish structured input instead of rejected bytes; keep targets deterministic and side-effect-free; seed with a high-quality starting corpus. [Source: Rust Fuzz Book — Structure-Aware Fuzzing](https://rust-fuzz.github.io/book/cargo-fuzz/structure-aware-fuzzing.html), [appsec.guide cargo-fuzz](https://appsec.guide/docs/fuzzing/rust/cargo-fuzz/)
- For `cargo-afl`: run `cargo afl system-config` once for kernel tuning, use `fuzz_with_reset!` to clear static state (stability), and disable CMPLOG (`-c -`) when running many instances. Fuzzing is most valuable for CLI input/file/format parsers. [Source: afl.rs](https://github.com/rust-fuzz/afl.rs)

### 4. Benchmark harnesses
- **`criterion`** is the established gold standard: statistical rigor (bootstrapped confidence intervals), baseline comparison, regression detection, and HTML reports. It recently got a perf fix so `cargo nextest run --benches`/`cargo test --benches` don't pay metadata/output-dir cost in test mode (PR #63, Mar 2026). [Source: criterion.rs commit #63](https://github.com/criterion-rs/criterion.rs/commit/569117113fcaba1a8868a3c7df507417514ccf5d)
- **`divan`** (0.1.x) is a modern, low-boilerplate alternative using `#[divan::bench]` attribute macros, faster to set up, and measures on par with criterion for mid-range workloads; several projects have migrated from criterion to divan for simplicity. [Source: Divan blog](https://nikolaivazquez.com/blog/divan/), [zenbench 3-way comparison](https://github.com/imazen/zenbench/commit/e4a30d5ccee9de9db11c58c02312e95bfe5c78da)
- Recommendation: use `criterion` for historical perf tracking/regression CI; `divan` for fast, low-friction local benches. Both belong in `benches/` and run on release builds only.

### 5. Mutation testing
- **`cargo-mutants`** (v27.0.0, Mar 2026) injects bugs (swap operators, replace return values, delete match arms) and checks whether your tests catch them. "Missed" mutants reveal weak assertions and untested branches. It's computationally expensive (rebuilds per mutant), so run it as a **scheduled CI job** (nightly/weekly), not per-PR; scope with `cargo mutants -f src/path.rs`. [Source: cargo-mutants](https://github.com/sourcefrog/cargo-mutants), [mutation patterns](https://mutants.rs/mutants.html)

### 6. Coverage & code quality tooling
- **`cargo-llvm-cov`** (taiki-e) is the modern recommended coverage tool using LLVM source-based instrumentation — precise line/region/branch coverage on Linux/macOS/Windows; integrates cleanly with nextest. Branch and doctest coverage still need nightly. **`cargo-tarpaulin`** (0.37) remains a stable alternative using ptrace/LLVM, good if you must stay on stable Rust. [Source: cargo-llvm-cov](https://github.com/taiki-e/cargo-llvm-cov), [Rust Project Primer — Coverage](https://www.rustprojectprimer.com/measure/coverage.html)
- **`clippy`** (800+ lints) is the standard linter — gate CI with `cargo clippy -- -D warnings` and consider `-D clippy::pedantic` (or curated subsets) for stricter quality. **`cargo fmt`** enforces style. **`cargo-audit`** (RustSec) and **`cargo-deny`** (0.20.2) check dependency licenses, advisories, sources, and duplicate/banned crates. [Source: Clippy](https://github.com/rust-lang/rust-clippy), [cargo-deny](https://github.com/EmbarkStudios/cargo-deny)
- Treat coverage % and mutation score as quality *metrics*, not goals — use them to find untested branches rather than chase 100%.

### 7. What a thorough strategy looks like for a Rust CLI tool
- **Structure:** split into a `lib.rs` (all logic, fully unit-tested) and a thin `main.rs` binary that only parses args and calls the lib — this is the single most important design decision for testability. (e.g., `clap` for arg parsing, `main.rs` delegates to `lib`.)
- **Unit tests** on pure functions in the lib; **integration tests** in `tests/` that invoke the built binary (use `assert_cmd` + `assert_fs` for `Command`, temp dirs, and stdout/stderr assertions) rather than calling internals.
- **Doctests** for public API examples; **`insta` snapshots** for CLI output/help/error rendering.
- For interactive/PTY behavior, consider `pitty` (real pseudo-terminal) since pipes miss line-editing/color/prompts.
- **Property tests** (`proptest`) for any parser or serializer; **fuzz targets** (`cargo-fuzz`) for file/argument/format ingestion.
- **Benchmarks** (`criterion`/`divan`) on hot paths (parsing, I/O loops, transforms).
- **CI gates (every PR):** `cargo fmt --check`, `cargo clippy -D warnings`, `cargo test`/`cargo nextest run`, `cargo audit`/`cargo deny check`, and `cargo llvm-cov` (target ~ meaningful line+branch coverage).
- **Scheduled CI:** `cargo mutants` mutation score; nightly `cargo-fuzz` corpus runs.
- Use mock/"safe mode" flags for integration tests that would otherwise hit the network or perform destructive ops, keeping the suite deterministic and environment-independent. [Source: Rust CLI testing strategy notes](https://github.com/dora-rs/dora/blob/main/docs/plan-agentic-qa-strategy.md), [pitty](https://github.com/kexi/pitty)

## Sources
- Kept: Rust Book — Test Organization (https://doc.rust-lang.org/stable/book/ch11-03-test-organization.html) — authoritative on unit/integration/doctest structure
- Kept: insta docs (https://docs.rs/insta/latest/insta/index.html) — snapshot testing API and workflow
- Kept: Proptest vs QuickCheck (https://proptest-rs.github.io/proptest/proptest/vs-quickcheck.html) — canonical comparison of prop-testing libs
- Kept: Rust Fuzz Book — Structure-Aware Fuzzing (https://rust-fuzz.github.io/book/cargo-fuzz/structure-aware-fuzzing.html) — cargo-fuzz best practices
- Kept: cargo-llvm-cov (https://github.com/taiki-e/cargo-llvm-cov) — modern coverage tool
- Kept: cargo-mutants (https://github.com/sourcefrog/cargo-mutants) — mutation testing
- Kept: cargo-nextest releases (https://github.com/nextest-rs/nextest/releases) — current runner (0.9.136)
- Kept: Clippy (https://github.com/rust-lang/rust-clippy) & cargo-deny (https://github.com/EmbarkStudios/cargo-deny) — linting/dependency quality
- Dropped: Several SEO/blog tutorials (LogRocket, Medium) — lower authority, superseded by primary docs
- Dropped: cli-testing-specialist crate — niche/AI-generated-suite tool, not core best practice

## Gaps
- No hard quantitative "recommended coverage %" or "mutation score target" is standardized across the ecosystem; teams set their own thresholds. Suggested next step: pick concrete thresholds (e.g., 80% line coverage, 0 "uncovered critical paths", weekly mutants run) once the CLI's code is visible.
- Specific CLI examples (file layout for `gor`) were not inspected; the strategy above is general. If you want, I can map it onto the actual `gor` repo structure.

## Supervisor coordination
No blocking decisions needed; research completed within scope.