mcpField
T
tdd-london-chicago

tdd-london-chicago

github.com/proffesor-for-testingテスト・品質519119 回インストール今日更新
リポジトリ

tdd-london-chicago について

ロンドン学派とシカゴ学派からテストスタイルを選ぶための、開発者やチーム向け TDD ガイドです。Red-Green-Refactor のサイクルや併用方法、エージェントとの連携を説明します。

主な機能

  1. 01コードの種類に応じたスタイル選択
  2. 02Red-Green-Refactor サイクルの実践
  3. 03実オブジェクトとモックの比較
  4. 04テスト手法の併用
  5. 05エージェントとの TDD 連携

活用シーン

  1. 01新機能をテストファーストで開発
  2. 02レガシーコードにテストを追加
  3. 03モックと実オブジェクトを選択
  4. 04チームへの TDD の説明

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/proffesor-for-testing/agentic-qe --skill tdd-london-chicago

インストール後、Claude Code で/tdd-london-chicagoを入力して読み込まれたか確認します。

同梱ファイルschemas/output.jsonscripts/validate-config.json

詳細

テスト駆動開発:ロンドン派とシカゴ派

<default_to_action> TDD を実践するとき、またはテストスタイルを選ぶとき:

  1. コードの種類を特定する:ドメインロジック → シカゴ派、外部依存関係 → ロンドン派
  2. 最初に失敗するテストを書く(Red フェーズ)
  3. テストを通すための最小限のコードを実装する(Green フェーズ)
  4. テストを成功させたままリファクタリングする(Refactor フェーズ)
  5. 次の機能についてサイクルを繰り返す

スタイル選択のクイックガイド:

  • 純粋関数/計算 → シカゴ派(実オブジェクト、状態の検証)
  • 依存関係のあるコントローラー/サービス → ロンドン派(モック、相互作用の検証)
  • 値オブジェクト → シカゴ派(最終状態をテスト)
  • API 統合 → ロンドン派(外部サービスをモック)
  • 実践では両方を組み合わせる(コントローラーにはロンドン派、ドメインにはシカゴ派)

成功の重要な要素:

  • テストで設計を導く。テストは単に検証するだけではありません
  • テストが実際に何かをテストしていることを確かめるため、最初に失敗させる
  • 最小限のコードを書く。テスト対象以外の機能は追加しない </default_to_action>

クイックリファレンスカード

使用する場面
  • テストファーストのアプローチで新機能を始めるとき
  • テストカバレッジのあるレガシーコードをリファクタリングするとき
  • チームに TDD の実践方法を教えるとき
  • モックと実オブジェクトのどちらを使うか選ぶとき
TDD サイクル
フェーズアクション規律
Red失敗するテストを書く失敗することを確認し、メッセージが明確か確かめる
Greenテストを通す最小限のコードを書く余分な機能を追加せず、リファクタリングもしない
Refactor構造を改善するテストを成功させたままにし、新しい機能は追加しない
各派の比較
観点シカゴ派(クラシシスト)ロンドン派(モキスト)
協調オブジェクト実オブジェクトモック/スタブ
検証状態(結果をアサート)相互作用(呼び出しをアサート)
分離性低め(統合されている)高め(単体のみ)
リファクタリング容易難しい(モックが壊れる)
設計へのフィードバック使用を通じて生まれる最初から明確
エージェントの連携
  • qe-test-generator:両方の派のテストを生成
  • qe-test-implementer:最小限のコードを実装(Green)
  • qe-test-refactorer:安全なリファクタリング(Refactor)

シカゴ派(状態ベース)

考え方: 公開 API を通じて観察可能な振る舞いをテストします。テストを利用側のコードに近づけます。

// State verification - test final outcome
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)
  • シンプルな協調処理
  • 新しいドメインを学ぶとき

ロンドン派(モックベース)

考え方: 各ユニットを分離してテストします。オブジェクト同士の協調方法に焦点を当てます。

// Interaction verification - test method calls
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);
  });
});

ロンドン派が力を発揮する場面:

  • 外部との統合(DB、API)
  • 副作用を伴うコマンドパターン
  • 複雑なワークフロー
  • 時間のかかる処理(ネットワーク、I/O)

混合アプローチ(推奨)

// London for controller (external deps)
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();
  });
});

// Chicago for domain logic
describe('OrderService', () => {
  it('applies discount when threshold met', () => {
    const service = new OrderService();
    const order = service.create({ items: [...], total: 150 });

    expect(order.discount).toBe(15); // 10% off > $100
  });
});

よくある落とし穴

❌ モックの使いすぎ(ロンドン派)
// BAD - mocking everything
const product = { getName: jest.fn(), getPrice: jest.fn() };

改善策: 外部依存関係のみをモックします。

❌ 内部実装のモック
// BAD - testing private methods
expect(order._calculateSubtotal).toHaveBeenCalled();

改善策: 公開されている振る舞いのみをテストします。

❌ テストの難しさは設計の問題
  • 多くのモックが必要ですか? → 依存関係が多すぎます
  • セットアップが難しいですか? → コンストラクターが多くの処理をしすぎています
  • データベースなしではテストできませんか? → 密結合の問題です

エージェント支援による TDD

// Agent generates tests in both schools
await Task("Generate Tests", {
  style: 'chicago',      // or 'london'
  target: 'src/domain/Order.ts',
  focus: 'state-verification'  // or 'collaboration-patterns'
}, "qe-test-generator");

// Agent-human ping-pong TDD
// Human writes test concept
const testIdea = "Order applies 10% discount when total > $100";

// Agent generates formal failing test (Red)
await Task("Create Failing Test", testIdea, "qe-test-generator");

// Human writes minimal code (Green)

// Agent suggests refactorings
await Task("Suggest Refactorings", { preserveTests: true }, "qe-test-refactorer");

エージェント連携のヒント

メモリ名前空間
aqe/tdd/
├── test-plan/*        - TDD session plans
├── red-phase/*        - Failing tests generated
├── green-phase/*      - Implementation code
└── refactor-phase/*   - Refactoring suggestions
フリート連携
const tddFleet = await FleetManager.coordinate({
  workflow: 'red-green-refactor',
  agents: {
    testGenerator: 'qe-test-generator',
    testExecutor: 'qe-test-executor',
    qualityAnalyzer: 'qe-quality-analyzer'
  },
  mode: 'sequential'
});

関連スキル


覚えておくこと

シカゴ派: 状態をテストし、実オブジェクトを使い、自由にリファクタリングする ロンドン派: 相互作用をテストし、依存関係をモックし、まずインターフェースを設計する 両方: 最初にテストを書き、通るようにし、リファクタリングする

どちらも「正解」ではありません。状況に応じて選び、必要に応じて組み合わせましょう。目標は、適切に設計され、テストされたコードです。

エージェントとの併用: エージェントはテストの生成、Green フェーズの検証、リファクタリングの提案を得意とします。人間が設計上の判断に集中できるよう、エージェントを使って TDD の規律を保ちましょう。

注意点

  • エージェントがレッドフェーズを飛ばし、テストと実装をまとめて作成してしまいます。コードを書く前にテストを実行し、「まずテストが失敗する」ことを徹底してください
  • ロンドン学派の過剰なモック化は、リファクタリングのたびに壊れる脆弱なテストを生みます。すべての関数ではなく、アーキテクチャ上の境界でモックしてください
  • シカゴ学派のテストは、統合の範囲が広がるにつれて遅くなります。テストの境界を狭く保ってください
  • エージェントは何でも jest.mock() で済ませがちです。テストしやすくするには、依存性注入を優先してください
  • リファクタリングのフェーズは、エージェントが最も手を抜きやすい場面です。テストの出力が同一であることを確認し、動作に変更がないことを検証してください

コメント