rtk-tdd
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseRust TDD Workflow
Rust TDD工作流
Three Laws of TDD
TDD三大定律
- Do NOT write production code without a failing test
- Write only enough test to fail (including compilation failure)
- 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(清理代码,执行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.
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)绝对不要跳过第2步。如果测试直接通过,说明它没有测试任何有效逻辑。
Idiomatic Rust Test Patterns
符合Rust惯用风格的测试模式
| Pattern | Usage | When |
|---|---|---|
| Arrange-Act-Assert | Base structure for every test | Always |
| Direct comparison / booleans | Deterministic values |
| Error path testing | Invalid inputs |
| Tests with | Fallible functions |
| Expected panic | Invariants, preconditions |
| File/I/O tests | Filesystem-dependent code |
| 模式 | 用法 | 适用场景 |
|---|---|---|
| Arrange-Act-Assert | 所有测试的基础结构 | 所有场景 |
| 直接比较 / 布尔值校验 | 确定性值校验 |
| 错误路径测试 | 无效输入场景 |
| 配合 | 可失败函数 |
| 预期会发生panic的场景 | 不变量、前置条件校验 |
| 文件/I/O测试 | 依赖文件系统的代码 |
Patterns by Code Type
按代码类型划分的测试模式
| Code Type | Test Pattern | Example |
|---|---|---|
| Pure function (str -> str) | Input literal -> assert output | |
| Parsing/filtering | Raw string -> filter -> contains/not-contains | |
| Validation/security | Boundary inputs -> assert bool | |
| Error handling | Bad input -> | |
| Struct/enum roundtrip | Construct -> serialize -> deserialize -> eq | |
| 代码类型 | 测试模式 | 示例 |
|---|---|---|
| 纯函数 (str -> str) | 输入字面量 -> 断言输出 | |
| 解析/过滤 | 原始字符串 -> 过滤 -> 包含/不包含校验 | |
| 校验/安全 | 边界输入 -> 断言布尔值 | |
| 错误处理 | 错误输入 -> | |
| 结构体/枚举序列化往返 | 构造 -> 序列化 -> 反序列化 -> 相等校验 | |
Naming Convention
命名规范
test_{function}_{scenario}
test_{function}_{input_type}Examples: , ,
test_truncate_edge_casetest_parse_invalid_inputtest_filter_empty_stringtest_{function}_{scenario}
test_{function}_{input_type}示例:、、
test_truncate_edge_casetest_parse_invalid_inputtest_filter_empty_stringWhen NOT to Use Pure TDD
不适合使用纯TDD的场景
- Functions calling -> test the parser, not the execution
Command::new() - -> refactor to
std::process::exit()first, then test the ResultResult - Direct I/O (SQLite, network) -> use tempfile/mock or test the pure logic separately
- Main/CLI wiring -> covered by integration/smoke tests
- 调用的函数 -> 测试解析逻辑,而非执行逻辑
Command::new() - 包含的代码 -> 先重构为返回
std::process::exit(),再测试返回的ResultResult - 直接I/O操作(SQLite、网络请求) -> 使用临时文件/Mock或者单独测试纯逻辑部分
- 主函数/CLI拼接逻辑 -> 由集成/冒烟测试覆盖
Pre-Commit Gate
预提交门禁检查
bash
cargo fmt --all --check
cargo clippy --all-targets
cargo testAll 3 must pass. No exceptions. No without documented justification.
#[allow(...)]bash
cargo fmt --all --check
cargo clippy --all-targets
cargo test三项必须全部通过,无例外。没有书面说明的情况下,不允许添加注解。
#[allow(...)]