测试驱动开发技能:伦敦与芝加哥学派Skill tdd-london-chicago

这个技能用于在软件开发中实施测试驱动开发(TDD),涵盖伦敦学派(基于模拟)和芝加哥学派(基于状态)的方法。它帮助开发者选择合适的测试风格,提高代码设计、测试覆盖率和代码质量。适用于领域逻辑、外部集成、算法计算等场景。关键词包括TDD、测试驱动开发、伦敦学派、芝加哥学派、模拟测试、状态验证、单元测试、集成测试、代码重构、测试风格选择。

测试 0 次安装 0 次浏览 更新于 3/9/2026

name: tdd-london-chicago description: “应用伦敦(基于模拟)和芝加哥(基于状态)的TDD学派。在实践测试驱动开发或为您的场景选择测试风格时使用。” category: development-practices priority: high tokenEstimate: 1100 agents: [qe-test-generator, qe-test-implementer, qe-test-refactorer] implementation_status: optimized optimization_version: 1.0 last_optimized: 2025-12-02 dependencies: [] quick_reference_card: true tags: [tdd, testing, london-school, chicago-school, red-green-refactor, mocks] trust_tier: 2 validation: schema_path: schemas/output.json validator_path: scripts/validate-config.json


测试驱动开发:伦敦与芝加哥学派

<default_to_action> 当实施TDD或选择测试风格时:

  1. 识别代码类型:领域逻辑 → 芝加哥,外部依赖 → 伦敦
  2. 首先编写失败测试(红色阶段)
  3. 实现最小化代码以通过(绿色阶段)
  4. 重构时保持测试通过(重构阶段)
  5. 为下一个功能重复循环

快速风格选择:

  • 纯函数/计算 → 芝加哥(真实对象,状态验证)
  • 控制器/服务带有依赖 → 伦敦(模拟,交互验证)
  • 值对象 → 芝加哥(测试最终状态)
  • API集成 → 伦敦(模拟外部服务)
  • 在实践中混合使用(伦敦用于控制器,芝加哥用于领域)

关键成功因素:

  • 测试驱动设计,而不仅仅是验证它
  • 首先使测试失败以确保它们测试了某些东西
  • 编写最小化代码 - 超出测试范围的功能不要添加 </default_to_action>

快速参考卡

何时使用

  • 以测试为先的方法开始新功能
  • 用测试覆盖重构遗留代码
  • 向团队教授TDD实践
  • 选择模拟与真实对象

TDD循环

阶段 行动 纪律
红色 编写失败测试 验证它失败,检查消息清晰
绿色 最小化代码以通过 无额外功能,不重构
重构 改进结构 保持测试通过,无新功能

学派比较

方面 芝加哥(经典学派) 伦敦(模拟学派)
协作者 真实对象 模拟/存根
验证 状态(断言结果) 交互(断言调用)
隔离 较低(集成) 较高(仅单元)
重构 更容易 更难(模拟中断)
设计反馈 从使用中产生 从一开始就明确

代理协调

  • qe-test-generator: 生成两个学派的测试
  • qe-test-implementer: 实现最小化代码(绿色)
  • qe-test-refactorer: 安全重构(重构)

芝加哥学派(基于状态)

哲学: 通过公共API测试可观察行为。保持测试接近消费者使用。

// 状态验证 - 测试最终结果
describe('Order', () => {
  it('calculates total with tax', () => {
    const order = new Order();
    order.addItem(new Product('Widget', 10.00), 2);
    order.addItem(new Product('Gadget', 15.00), 1);

    expect(order.totalWithTax(0.10)).toBe(38.50);
  });
});

芝加哥学派闪耀时:

  • 具有清晰状态的领域逻辑
  • 算法和计算
  • 值对象(Money, Email
  • 简单协作
  • 学习新领域

伦敦学派(基于模拟)

哲学: 隔离测试每个单元。关注对象如何协作。

// 交互验证 - 测试方法调用
describe('Order', () => {
  it('delegates tax calculation', () => {
    const taxCalculator = {
      calculateTax: jest.fn().mockReturnValue(3.50)
    };
    const order = new Order(taxCalculator);
    order.addItem({ price: 10 }, 2);

    order.totalWithTax();

    expect(taxCalculator.calculateTax).toHaveBeenCalledWith(20.00);
  });
});

伦敦学派闪耀时:

  • 外部集成(数据库、API)
  • 带有副作用的命令模式
  • 复杂工作流
  • 慢速操作(网络、I/O)

混合方法(推荐)

// 伦敦用于控制器(外部依赖)
describe('OrderController', () => {
  it('creates order and sends confirmation', async () => {
    const orderService = { create: jest.fn().mockResolvedValue({ id: 123 }) };
    const emailService = { send: jest.fn() };

    const controller = new OrderController(orderService, emailService);
    await controller.placeOrder(orderData);

    expect(orderService.create).toHaveBeenCalledWith(orderData);
    expect(emailService.send).toHaveBeenCalled();
  });
});

// 芝加哥用于领域逻辑
describe('OrderService', () => {
  it('applies discount when threshold met', () => {
    const service = new OrderService();
    const order = service.create({ items: [...], total: 150 });

    expect(order.discount).toBe(15); // 当总额超过$100时打10%折扣
  });
});

常见陷阱

❌ 过度模拟(伦敦学派)

// 错误 - 模拟一切
const product = { getName: jest.fn(), getPrice: jest.fn() };

更好: 仅模拟外部依赖。

❌ 模拟内部

// 错误 - 测试私有方法
expect(order._calculateSubtotal).toHaveBeenCalled();

更好: 仅测试公共行为。

❌ 测试痛苦 = 设计痛苦

  • 需要许多模拟? → 依赖过多
  • 难以设置? → 构造函数做得太多
  • 没有数据库无法测试? → 耦合问题

代理辅助的TDD

// 代理生成两个学派的测试
await Task("Generate Tests", {
  style: 'chicago',      // 或 'london'
  target: 'src/domain/Order.ts',
  focus: 'state-verification'  // 或 'collaboration-patterns'
}, "qe-test-generator");

// 代理-人类乒乓式TDD
// 人类编写测试概念
const testIdea = "Order applies 10% discount when total > $100";

// 代理生成正式的失败测试(红色)
await Task("Create Failing Test", testIdea, "qe-test-generator");

// 人类编写最小化代码(绿色)

// 代理建议重构
await Task("Suggest Refactorings", { preserveTests: true }, "qe-test-refactorer");

代理协调提示

内存命名空间

aqe/tdd/
├── test-plan/*        - TDD会话计划
├── red-phase/*        - 生成的失败测试
├── green-phase/*      - 实现代码
└── refactor-phase/*   - 重构建议

舰队协调

const tddFleet = await FleetManager.coordinate({
  workflow: 'red-green-refactor',
  agents: {
    testGenerator: 'qe-test-generator',
    testExecutor: 'qe-test-executor',
    qualityAnalyzer: 'qe-quality-analyzer'
  },
  mode: 'sequential'
});

相关技能


记住

芝加哥: 测试状态,使用真实对象,自由重构 伦敦: 测试交互,模拟依赖,首先设计接口 两者: 首先编写测试,使其通过,重构

没有“正确”的学派。根据上下文选择。根据需要混合。目标:设计良好、测试过的代码。

使用代理: 代理擅长生成测试、验证绿色阶段和建议重构。使用代理以保持TDD纪律,同时人类专注于设计决策。