tdd-london-chicago について
ロンドン学派とシカゴ学派からテストスタイルを選ぶための、開発者やチーム向け TDD ガイドです。Red-Green-Refactor のサイクルや併用方法、エージェントとの連携を説明します。
主な機能
- 01コードの種類に応じたスタイル選択
- 02Red-Green-Refactor サイクルの実践
- 03実オブジェクトとモックの比較
- 04テスト手法の併用
- 05エージェントとの TDD 連携
活用シーン
- 01新機能をテストファーストで開発
- 02レガシーコードにテストを追加
- 03モックと実オブジェクトを選択
- 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 を実践するとき、またはテストスタイルを選ぶとき:
- コードの種類を特定する:ドメインロジック → シカゴ派、外部依存関係 → ロンドン派
- 最初に失敗するテストを書く(Red フェーズ)
- テストを通すための最小限のコードを実装する(Green フェーズ)
- テストを成功させたままリファクタリングする(Refactor フェーズ)
- 次の機能についてサイクルを繰り返す
スタイル選択のクイックガイド:
- 純粋関数/計算 → シカゴ派(実オブジェクト、状態の検証)
- 依存関係のあるコントローラー/サービス → ロンドン派(モック、相互作用の検証)
- 値オブジェクト → シカゴ派(最終状態をテスト)
- 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'
});
関連スキル
- agentic-quality-engineering - エージェント連携による TDD
- refactoring-patterns - Refactor フェーズの手法
- api-testing-patterns - API テストにおけるロンドン派
覚えておくこと
シカゴ派: 状態をテストし、実オブジェクトを使い、自由にリファクタリングする ロンドン派: 相互作用をテストし、依存関係をモックし、まずインターフェースを設計する 両方: 最初にテストを書き、通るようにし、リファクタリングする
どちらも「正解」ではありません。状況に応じて選び、必要に応じて組み合わせましょう。目標は、適切に設計され、テストされたコードです。
エージェントとの併用: エージェントはテストの生成、Green フェーズの検証、リファクタリングの提案を得意とします。人間が設計上の判断に集中できるよう、エージェントを使って TDD の規律を保ちましょう。
注意点
- エージェントがレッドフェーズを飛ばし、テストと実装をまとめて作成してしまいます。コードを書く前にテストを実行し、「まずテストが失敗する」ことを徹底してください
- ロンドン学派の過剰なモック化は、リファクタリングのたびに壊れる脆弱なテストを生みます。すべての関数ではなく、アーキテクチャ上の境界でモックしてください
- シカゴ学派のテストは、統合の範囲が広がるにつれて遅くなります。テストの境界を狭く保ってください
- エージェントは何でも
jest.mock()で済ませがちです。テストしやすくするには、依存性注入を優先してください - リファクタリングのフェーズは、エージェントが最も手を抜きやすい場面です。テストの出力が同一であることを確認し、動作に変更がないことを検証してください