tdd
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinese/tdd -- Red-Green-Refactor for .NET
/tdd -- .NET 的红-绿-重构工作流
What
概述
Guides a strict test-driven development cycle for .NET features. Instead of
writing implementation first and bolting on tests after, this command flips the
order: write a failing test that defines the desired behavior, implement the
minimum code to make it pass, then refactor with confidence.
Every cycle uses the .NET testing stack:
- xUnit v3 -- Test framework with and
[Fact][Theory] - WebApplicationFactory -- Integration tests against the real HTTP pipeline
- Testcontainers -- Real databases (PostgreSQL, SQL Server) in tests
- Verify -- Snapshot testing for complex response structures
- FakeTimeProvider -- Deterministic time in tests
指导.NET功能的严格测试驱动开发循环。不同于先编写实现代码再附加测试,此命令颠倒顺序:先编写一个定义预期行为的失败测试,再编写最少代码使其通过,最后自信地进行重构。
每个循环使用.NET测试栈:
- xUnit v3 -- 支持和
[Fact]的测试框架[Theory] - WebApplicationFactory -- 针对真实HTTP管道的集成测试
- Testcontainers -- 在测试中使用真实数据库(PostgreSQL、SQL Server)
- Verify -- 针对复杂响应结构的快照测试
- FakeTimeProvider -- 测试中的确定性时间
When
适用场景
- User says "TDD", "test-driven", "let's TDD this", "write the test first"
- Building a new feature with clear acceptance criteria
- Fixing a bug (write a test that reproduces the bug first, then fix)
- Adding behavior to an existing feature (test the new behavior first)
- Any time the user wants proof that code works before it ships
Skip TDD for: Trivial config changes, scaffolding without logic, documentation.
- 用户提及"TDD"、"test-driven"、"let's TDD this"、"write the test first"时
- 构建具有明确验收标准的新功能时
- 修复bug时(先编写重现bug的测试,再修复)
- 为现有功能添加行为时(先测试新行为)
- 任何用户希望在代码交付前证明其有效的场景
跳过TDD的场景: 琐碎的配置更改、无逻辑的脚手架搭建、文档编写。
How
实施流程
Cycle: Red -> Green -> Refactor
循环:红 → 绿 → 重构
Each feature goes through one or more TDD cycles. A cycle covers one discrete behavior.
每个功能需经历一个或多个TDD循环。一个循环对应一个独立的行为。
Step 1: Red -- Write the Failing Test
步骤1:红阶段 -- 编写失败的测试
Write a test that describes the desired behavior. The test MUST fail because the
implementation does not exist yet.
csharp
[Fact]
public async Task CreateOrder_WithValidItems_Returns201WithOrderId()
{
// Arrange
var client = _factory.CreateClient();
var request = new CreateOrderRequest([
new OrderItemRequest("SKU-001", 2, 29.99m)
]);
// Act
var response = await client.PostAsJsonAsync("/api/orders", request);
// Assert — plain xUnit Assert (FluentAssertions v8+ requires a commercial license)
Assert.Equal(HttpStatusCode.Created, response.StatusCode);
var result = await response.Content.ReadFromJsonAsync<CreateOrderResponse>();
Assert.NotNull(result);
Assert.NotEqual(Guid.Empty, result.OrderId);
}Run the test and confirm it fails:
bash
dotnet test --filter "CreateOrder_WithValidItems_Returns201WithOrderId"If the test passes without implementation, the test is not testing what you think.
Rewrite it.
编写描述预期行为的测试。由于实现代码尚未存在,测试必须失败。
csharp
[Fact]
public async Task CreateOrder_WithValidItems_Returns201WithOrderId()
{
// Arrange
var client = _factory.CreateClient();
var request = new CreateOrderRequest([
new OrderItemRequest("SKU-001", 2, 29.99m)
]);
// Act
var response = await client.PostAsJsonAsync("/api/orders", request);
// Assert — 原生xUnit断言(FluentAssertions v8+需要商业许可)
Assert.Equal(HttpStatusCode.Created, response.StatusCode);
var result = await response.Content.ReadFromJsonAsync<CreateOrderResponse>();
Assert.NotNull(result);
Assert.NotEqual(Guid.Empty, result.OrderId);
}运行测试并确认失败:
bash
dotnet test --filter "CreateOrder_WithValidItems_Returns201WithOrderId"如果未编写实现代码测试就通过,说明测试未覆盖预期内容,请重写测试。
Step 2: Green -- Minimal Implementation
步骤2:绿阶段 -- 最小化实现
Write the minimum code to make the test pass. Do not add features, optimizations,
or edge case handling. The goal is a green test, nothing more.
- Create the endpoint, handler, request/response types, and EF config as needed
- Use the simplest logic that satisfies the test assertion
- Do not refactor yet -- ugly passing code is fine at this stage
Run the test and confirm it passes:
bash
dotnet test --filter "CreateOrder_WithValidItems_Returns201WithOrderId"编写最少代码使测试通过。不要添加额外功能、优化或边缘情况处理。目标仅为让测试通过。
- 根据需要创建端点、处理器、请求/响应类型和EF配置
- 使用满足测试断言的最简单逻辑
- 此时无需重构——丑陋但能通过的代码是可接受的
运行测试并确认通过:
bash
dotnet test --filter "CreateOrder_WithValidItems_Returns201WithOrderId"Step 3: Refactor -- Clean Up with Confidence
步骤3:重构阶段 -- 自信地优化代码
Now that the test is green, refactor freely:
- Extract methods, rename variables, improve structure
- Apply modern C# patterns (primary constructors, records, collection expressions)
- Add validation, error handling, and edge cases (with new tests for each)
- Run the full test suite after each refactor step to catch regressions
bash
dotnet testIf any test goes red during refactoring, undo the last change and try a smaller step.
测试通过后,可自由重构:
- 提取方法、重命名变量、优化结构
- 应用现代C#模式(主构造函数、记录、集合表达式)
- 添加验证、错误处理和边缘情况(为每种情况编写新测试)
- 每次重构后运行完整测试套件,避免回归问题
bash
dotnet test如果重构期间任何测试失败,撤销最后一次更改,尝试更小的重构步骤。
Multi-Cycle Features
多循环功能
Most features require multiple TDD cycles. Plan the cycles upfront:
Feature: Order Management
Cycle 1: Create order with valid items -> 201
Cycle 2: Create order with empty items -> 400 validation error
Cycle 3: Create order with invalid SKU -> 400 with specific error
Cycle 4: Get order by ID -> 200 with full order details
Cycle 5: Get order that does not exist -> 404Each cycle adds one behavior. Never combine multiple behaviors in a single cycle.
大多数功能需要多个TDD循环,请提前规划:
Feature: Order Management
Cycle 1: 创建包含有效商品的订单 -> 返回201状态码
Cycle 2: 创建空商品订单 -> 返回400验证错误
Cycle 3: 创建包含无效SKU的订单 -> 返回400特定错误
Cycle 4: 通过ID查询订单 -> 返回200及完整订单详情
Cycle 5: 查询不存在的订单 -> 返回404状态码每个循环添加一个行为。切勿在单个循环中合并多个行为。
Test Infrastructure Setup
测试基础设施搭建
If the project lacks test infrastructure, set it up before the first cycle:
- Create test project with xUnit v3 and required packages
- Configure with Testcontainers for the real database
WebApplicationFactory - Add a shared fixture to avoid spinning up containers per test class
- Verify the infrastructure with a simple health-check test
如果项目缺少测试基础设施,请在第一个循环前完成设置:
- 创建包含xUnit v3和所需包的测试项目
- 配置,使用Testcontainers连接真实数据库
WebApplicationFactory - 添加共享夹具,避免为每个测试类启动容器
- 使用简单的健康检查测试验证基础设施
Example
示例
User: /tdd Let's TDD a product search endpoint
Claude: I'll plan the TDD cycles for product search:
Cycle 1: Search with matching term returns matching products
Cycle 2: Search with no matches returns empty list
Cycle 3: Search with pagination returns correct page
Cycle 4: Search with filters narrows results
Starting Cycle 1: Red phase
Writing a failing integration test for basic product search...
[writes test, runs it, confirms failure]
Cycle 1: Green phase
Implementing the minimum to make the search test pass...
[implements, runs test, confirms pass]
Cycle 1: Refactor phase
The implementation works but the query could use a projection
instead of loading full entities. Refactoring...
[refactors, runs full suite, all green]
Cycle 1 complete. Moving to Cycle 2...用户: /tdd 我们来对产品搜索端点进行TDD开发
Claude: 我将为产品搜索规划TDD循环:
Cycle 1: 使用匹配关键词搜索返回匹配产品
Cycle 2: 无匹配关键词搜索返回空列表
Cycle 3: 带分页的搜索返回正确页面
Cycle 4: 带筛选条件的搜索缩小结果范围
开始Cycle 1:红阶段
编写一个失败的基础产品搜索集成测试...
[编写测试,运行并确认失败]
Cycle 1:绿阶段
编写最少代码使搜索测试通过...
[实现代码,运行测试并确认通过]
Cycle 1:重构阶段
实现代码可行,但查询可以使用投影而非加载完整实体。开始重构...
[重构代码,运行完整测试套件,全部通过]
Cycle 1完成。进入Cycle 2...Related
相关命令
- -- Run full verification after completing all TDD cycles
/verify - -- Generate initial feature structure that tests will drive
/scaffold
- -- 完成所有TDD循环后运行完整验证
/verify - -- 生成测试将驱动的初始功能结构
/scaffold