rtk-ai/rtk

rtk-tdd

Enforces TDD (Red-Green-Refactor) for Rust development.

Voir la source
Document Skill original

Rendu depuis le dépôt source en conservant titres, exemples, code, tableaux, liens et images.

Rust TDD Workflow

Three Laws of TDD

  1. Do NOT write production code without a failing test
  2. Write only enough test to fail (including compilation failure)
  3. Write only enough production code to pass the failing test

Cycle: RED (test fails) -> GREEN (minimum to pass) -> REFACTOR (cleanup, cargo test)

Red-Green-Refactor Steps

1. Write test in #[cfg(test)] mod tests of the SAME file
2. cargo test MODULE::tests::test_name  -- must FAIL (red)
3. Implement the minimum in the function
4. cargo test MODULE::tests::test_name  -- must PASS (green)
5. Refactor if needed, re-run cargo test (still green)
6. cargo fmt && cargo clippy --all-targets && cargo test  (final gate)

Never skip step 2. If the test passes immediately, it tests nothing.

Idiomatic Rust Test Patterns

PatternUsageWhen
Arrange-Act-AssertBase structure for every testAlways
assert_eq! / assert!Direct comparison / booleansDeterministic values
assert!(result.is_err())Error path testingInvalid inputs
Result<()> return typeTests with ? operatorFallible functions
#[should_panic]Expected panicInvariants, preconditions
tempfile::NamedTempFileFile/I/O testsFilesystem-dependent code

Patterns by Code Type

Code TypeTest PatternExample
Pure function (str -> str)Input literal -> assert outputassert_eq!(truncate("hello", 3), "...")
Parsing/filteringRaw string -> filter -> contains/not-containsassert!(filter(raw).contains("expected"))
Validation/securityBoundary inputs -> assert boolassert!(!is_valid("../etc/passwd"))
Error handlingBad input -> is_err()assert!(parse("garbage").is_err())
Struct/enum roundtripConstruct -> serialize -> deserialize -> eqassert_eq!(from_str(to_str(x)), x)

Naming Convention

test_{function}_{scenario}
test_{function}_{input_type}

Examples: test_truncate_edge_case, test_parse_invalid_input, test_filter_empty_string

When NOT to Use Pure TDD

  • Functions calling Command::new() -> test the parser, not the execution
  • std::process::exit() -> refactor to Result first, then test the Result
  • Direct I/O (SQLite, network) -> use tempfile/mock or test the pure logic separately
  • Main/CLI wiring -> covered by integration/smoke tests

Pre-Commit Gate

bash
cargo fmt --all --check
cargo clippy --all-targets
cargo test

All 3 must pass. No exceptions. No #[allow(...)] without documented justification.

du même dépôt

Autres Skills

Tous les Skills