docs(zh-CN): sync Chinese docs with latest upstream changes

This commit is contained in:
neo
2026-03-21 12:55:58 +08:00
parent 0af0fbf40b
commit e73c2ffa34
85 changed files with 11028 additions and 747 deletions

View File

@@ -0,0 +1,311 @@
---
description: 为Rust强制执行TDD工作流。先写测试然后实现。使用cargo-llvm-cov验证80%以上的覆盖率。
---
# Rust TDD 命令
该命令使用 `#[test]`、rstest、proptest 和 mockall 来强制执行 Rust 代码的测试驱动开发方法。
## 该命令的作用
1. **定义类型/特征**:使用 `todo!()` 搭建函数签名
2. **编写测试**创建全面的测试模块RED
3. **运行测试**:验证测试因正确的原因而失败
4. **实现代码**编写通过测试所需的最少代码GREEN
5. **重构**:在保持测试通过的前提下进行改进
6. **检查覆盖率**:使用 cargo-llvm-cov 确保 80%+ 的覆盖率
## 何时使用
在以下情况使用 `/rust-test`
* 实现新的 Rust 函数、方法或特征时
* 为现有 Rust 代码添加测试覆盖时
* 修复错误时(首先编写失败的测试)
* 构建关键业务逻辑时
* 学习 Rust 中的 TDD 工作流程时
## TDD 循环
```
RED -> Write failing test first
GREEN -> Implement minimal code to pass
REFACTOR -> Improve code, tests stay green
REPEAT -> Next test case
```
## 示例会话
````text
User: /rust-test I need a function to validate user registration
Agent:
# TDD Session: Registration Validator
## Step 1: Define Interface
```rust
// src/validator.rs
pub struct RegistrationRequest {
pub name: String,
pub email: String,
pub password: String,
}
pub enum ValidationResult {
Valid,
Invalid(Vec<String>),
}
pub fn validate_registration(request: &RegistrationRequest) -> ValidationResult {
todo!()
}
```
## Step 2: Write Tests (RED)
```rust
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn valid_registration_returns_valid() {
let request = RegistrationRequest {
name: "Alice".into(),
email: "alice@example.com".into(),
password: "SecureP@ss1".into(),
};
assert!(matches!(validate_registration(&request), ValidationResult::Valid));
}
#[test]
fn blank_name_returns_invalid() {
let request = RegistrationRequest {
name: "".into(),
email: "alice@example.com".into(),
password: "SecureP@ss1".into(),
};
match validate_registration(&request) {
ValidationResult::Invalid(errors) => {
assert!(errors.contains(&"Name is required".to_string()));
}
ValidationResult::Valid => panic!("expected Invalid"),
}
}
#[test]
fn invalid_email_returns_invalid() {
let request = RegistrationRequest {
name: "Alice".into(),
email: "not-an-email".into(),
password: "SecureP@ss1".into(),
};
assert!(matches!(
validate_registration(&request),
ValidationResult::Invalid(_)
));
}
#[test]
fn short_password_returns_invalid() {
let request = RegistrationRequest {
name: "Alice".into(),
email: "alice@example.com".into(),
password: "short".into(),
};
assert!(matches!(
validate_registration(&request),
ValidationResult::Invalid(_)
));
}
}
```
## Step 3: Run Tests — Verify FAIL
```bash
$ cargo test
running 4 tests
test tests::valid_registration_returns_valid ... FAILED (not yet implemented)
test tests::blank_name_returns_invalid ... FAILED
test tests::invalid_email_returns_invalid ... FAILED
test tests::short_password_returns_invalid ... FAILED
```
Tests fail as expected (todo! panic).
## Step 4: Implement Minimal Code (GREEN)
```rust
pub fn validate_registration(request: &RegistrationRequest) -> ValidationResult {
let mut errors = Vec::new();
if request.name.trim().is_empty() {
errors.push("Name is required".into());
}
if !request.email.contains('@') {
errors.push("Invalid email format".into());
}
if request.password.len() < 8 {
errors.push("Password must be at least 8 characters".into());
}
if errors.is_empty() {
ValidationResult::Valid
} else {
ValidationResult::Invalid(errors)
}
}
```
## Step 5: Run Tests — Verify PASS
```bash
$ cargo test
running 4 tests
test tests::valid_registration_returns_valid ... ok
test tests::blank_name_returns_invalid ... ok
test tests::invalid_email_returns_invalid ... ok
test tests::short_password_returns_invalid ... ok
test result: ok. 4 passed; 0 failed
```
All tests passing!
## Step 6: Check Coverage
```bash
$ cargo llvm-cov
Coverage: 100.0% of lines
```
Coverage: 100%
## TDD Complete!
````
## 测试模式
### 单元测试
```rust
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn adds_two_numbers() {
assert_eq!(add(2, 3), 5);
}
#[test]
fn handles_error() -> Result<(), Box<dyn std::error::Error>> {
let result = parse_config(r#"port = 8080"#)?;
assert_eq!(result.port, 8080);
Ok(())
}
}
```
### 使用 rstest 进行参数化测试
```rust
use rstest::{rstest, fixture};
#[rstest]
#[case("hello", 5)]
#[case("", 0)]
#[case("rust", 4)]
fn test_string_length(#[case] input: &str, #[case] expected: usize) {
assert_eq!(input.len(), expected);
}
```
### 异步测试
```rust
#[tokio::test]
async fn fetches_data_successfully() {
let client = TestClient::new().await;
let result = client.get("/data").await;
assert!(result.is_ok());
}
```
### 基于属性的测试
```rust
use proptest::prelude::*;
proptest! {
#[test]
fn encode_decode_roundtrip(input in ".*") {
let encoded = encode(&input);
let decoded = decode(&encoded).unwrap();
assert_eq!(input, decoded);
}
}
```
## 覆盖率命令
```bash
# Summary report
cargo llvm-cov
# HTML report
cargo llvm-cov --html
# Fail if below threshold
cargo llvm-cov --fail-under-lines 80
# Run specific test
cargo test test_name
# Run with output
cargo test -- --nocapture
# Run without stopping on first failure
cargo test --no-fail-fast
```
## 覆盖率目标
| 代码类型 | 目标 |
|-----------|--------|
| 关键业务逻辑 | 100% |
| 公共 API | 90%+ |
| 通用代码 | 80%+ |
| 生成的 / FFI 绑定 | 排除 |
## TDD 最佳实践
**应做:**
* **首先**编写测试,在任何实现之前
* 每次更改后运行测试
* 使用 `assert_eq!` 而非 `assert!` 以获得更好的错误信息
* 在返回 `Result` 的测试中使用 `?` 以获得更清晰的输出
* 测试行为,而非实现
* 包含边界情况(空值、边界值、错误路径)
**不应做:**
* 在测试之前编写实现
* 跳过 RED 阶段
* 在 `Result::is_err()` 可用时使用 `#[should_panic]`
* 在测试中使用 `sleep()` — 应使用通道或 `tokio::time::pause()`
* 模拟一切 — 在可行时优先使用集成测试
## 相关命令
* `/rust-build` - 修复构建错误
* `/rust-review` - 在实现后审查代码
* `/verify` - 运行完整的验证循环
## 相关
* 技能:`skills/rust-testing/`
* 技能:`skills/rust-patterns/`