Back to Skills

tdd-london-chicago

proffesor-for-testing
Updated Today
115 views
99
21
99
View on GitHub
Othertddtestinglondon-schoolchicago-schoolred-green-refactormocks

About

This skill helps developers apply London (mock-based) and Chicago (state-based) TDD approaches when practicing test-driven development. It guides style selection based on code type—using Chicago for domain logic and London for external dependencies—and provides structured support through the Red-Green-Refactor cycle. Key capabilities include generating, implementing, and refactoring tests with optimized agents for each phase.

Quick Install

Claude Code

Recommended
Plugin CommandRecommended
/plugin add https://github.com/proffesor-for-testing/agentic-qe
Git CloneAlternative
git clone https://github.com/proffesor-for-testing/agentic-qe.git ~/.claude/skills/tdd-london-chicago

Copy and paste this command in Claude Code to install this skill

Documentation

Test-Driven Development: London & Chicago Schools

<default_to_action> When implementing TDD or choosing testing style:

  1. IDENTIFY code type: domain logic → Chicago, external deps → London
  2. WRITE failing test first (Red phase)
  3. IMPLEMENT minimal code to pass (Green phase)
  4. REFACTOR while keeping tests green (Refactor phase)
  5. REPEAT cycle for next functionality

Quick Style Selection:

  • Pure functions/calculations → Chicago (real objects, state verification)
  • Controllers/services with deps → London (mocks, interaction verification)
  • Value objects → Chicago (test final state)
  • API integrations → London (mock external services)
  • Mix both in practice (London for controllers, Chicago for domain)

Critical Success Factors:

  • Tests drive design, not just verify it
  • Make tests fail first to ensure they test something
  • Write minimal code - no features beyond what's tested </default_to_action>

Quick Reference Card

When to Use

  • Starting new feature with test-first approach
  • Refactoring legacy code with test coverage
  • Teaching TDD practices to team
  • Choosing between mocking vs real objects

TDD Cycle

PhaseActionDiscipline
RedWrite failing testVerify it fails, check message is clear
GreenMinimal code to passNo extra features, don't refactor
RefactorImprove structureKeep tests passing, no new functionality

School Comparison

AspectChicago (Classicist)London (Mockist)
CollaboratorsReal objectsMocks/stubs
VerificationState (assert outcomes)Interaction (assert calls)
IsolationLower (integrated)Higher (unit only)
RefactoringEasierHarder (mocks break)
Design feedbackEmerges from useExplicit from start

Agent Coordination

  • qe-test-generator: Generate tests in both schools
  • qe-test-implementer: Implement minimal code (Green)
  • qe-test-refactorer: Safe refactoring (Refactor)

Chicago School (State-Based)

Philosophy: Test observable behavior through public API. Keep tests close to consumer usage.

// 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);
  });
});

When Chicago Shines:

  • Domain logic with clear state
  • Algorithms and calculations
  • Value objects (Money, Email)
  • Simple collaborations
  • Learning new domain

London School (Mock-Based)

Philosophy: Test each unit in isolation. Focus on how objects collaborate.

// 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);
  });
});

When London Shines:

  • External integrations (DB, APIs)
  • Command patterns with side effects
  • Complex workflows
  • Slow operations (network, I/O)

Mixed Approach (Recommended)

// 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
  });
});

Common Pitfalls

❌ Over-Mocking (London)

// BAD - mocking everything
const product = { getName: jest.fn(), getPrice: jest.fn() };

Better: Only mock external dependencies.

❌ Mocking Internals

// BAD - testing private methods
expect(order._calculateSubtotal).toHaveBeenCalled();

Better: Test public behavior only.

❌ Test Pain = Design Pain

  • Need many mocks? → Too many dependencies
  • Hard to set up? → Constructor does too much
  • Can't test without database? → Coupling issue

Agent-Assisted 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");

Agent Coordination Hints

Memory Namespace

aqe/tdd/
├── test-plan/*        - TDD session plans
├── red-phase/*        - Failing tests generated
├── green-phase/*      - Implementation code
└── refactor-phase/*   - Refactoring suggestions

Fleet Coordination

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

Related Skills


Remember

Chicago: Test state, use real objects, refactor freely London: Test interactions, mock dependencies, design interfaces first Both: Write the test first, make it pass, refactor

Neither is "right." Choose based on context. Mix as needed. Goal: well-designed, tested code.

With Agents: Agents excel at generating tests, validating green phase, and suggesting refactorings. Use agents to maintain TDD discipline while humans focus on design decisions.

GitHub Repository

proffesor-for-testing/agentic-qe
Path: .claude/skills/tdd-london-chicago
agenticqeagenticsfoundationagentsquality-engineering

Related Skills

evaluating-llms-harness

Testing

This Claude Skill runs the lm-evaluation-harness to benchmark LLMs across 60+ standardized academic tasks like MMLU and GSM8K. It's designed for developers to compare model quality, track training progress, or report academic results. The tool supports various backends including HuggingFace and vLLM models.

View skill

webapp-testing

Testing

This Claude Skill provides a Playwright-based toolkit for testing local web applications through Python scripts. It enables frontend verification, UI debugging, screenshot capture, and log viewing while managing server lifecycles. Use it for browser automation tasks but run scripts directly rather than reading their source code to avoid context pollution.

View skill

finishing-a-development-branch

Testing

This skill helps developers complete finished work by verifying tests pass and then presenting structured integration options. It guides the workflow for merging, creating PRs, or cleaning up branches after implementation is done. Use it when your code is ready and tested to systematically finalize the development process.

View skill

content-collections

Meta

This skill provides a production-tested setup for Content Collections, a TypeScript-first tool that transforms Markdown/MDX files into type-safe data collections with Zod validation. Use it when building blogs, documentation sites, or content-heavy Vite + React applications to ensure type safety and automatic content validation. It covers everything from Vite plugin configuration and MDX compilation to deployment optimization and schema validation.

View skill