Test-Driven Development (TDD)
Also Known As
TDD
test-first development
red-green-refactor
TL;DR
A development practice where tests are written before production code, driving design through the Red-Green-Refactor cycle.
Explanation
TDD follows a tight cycle: (1) write a failing test (Red), (2) write the minimum code to make it pass (Green), (3) refactor for quality while keeping tests green. Writing tests first forces clarity about requirements before implementation, produces naturally testable code (small, focused, with injected dependencies), and creates a comprehensive test suite as a by-product. TDD is a design activity as much as a testing activity — the pain of writing tests signals design problems. Outside-in TDD (starting from integration/acceptance tests) is called ATDD or BDD.
Diagram
flowchart LR
RED[Write failing test<br/>RED] -->|implement code| GREEN[Make test pass<br/>GREEN]
GREEN -->|improve code| REFACTOR[Refactor<br/>BLUE]
REFACTOR -->|write next test| RED
subgraph Benefits
DESIGN[Forces thinking about API<br/>before implementation]
COVERAGE2[100pct coverage by default<br/>only code tests need]
SAFETY[Refactor safely<br/>tests catch regressions]
end
subgraph TDD_vs_Tests_After
AFTER[Tests after - verify it works]
TDD2[TDD - design tool + verification]
end
style RED fill:#f85149,color:#fff
style GREEN fill:#238636,color:#fff
style REFACTOR fill:#1f6feb,color:#fff
Common Misconception
✗ TDD means writing tests before every line of code, forever. TDD is a design technique — the tests drive you toward loosely coupled, testable code. Many experienced practitioners use it selectively for complex logic rather than mechanically for all code.
Why It Matters
TDD forces you to design the API of your code before implementing it — tests written first expose awkward interfaces immediately, when they are cheap to fix. The test suite that emerges is comprehensive by construction, not bolted on after.
Common Mistakes
- Writing all tests first, then all implementation — TDD is red/green/refactor per small cycle, not a waterfall.
- Skipping the refactor step — without it TDD produces working but messy code.
- Writing tests that are too large — each cycle should test one specific behaviour.
- Abandoning TDD when time pressure hits — this is exactly when having tests matters most.
Code Examples
✗ Vulnerable
// Test-last approach — code written first, then retrofitted with tests:
class UserService {
public function create(array $data): User {
// 100 lines of code written without tests
// Now write tests that 'fit' the existing code
// Tests describe implementation, not behaviour
}
}
// TDD: test first → drives minimal implementation → refactor safely
✓ Fixed
// RED: write a failing test first
public function test_discount_applied_for_vip(): void {
$pricing = new PricingService();
$price = $pricing->calculate(product: $product, customer: $vip);
$this->assertEquals(90.00, $price); // FAILS — method doesn't exist yet
}
// GREEN: write the minimum code to pass
class PricingService {
public function calculate(Product $product, Customer $customer): float {
$price = $product->basePrice;
if ($customer->isVip()) $price *= 0.9;
return $price;
}
}
// REFACTOR: clean up while tests stay green
Tags
🤝 Adopt this term
£79/year · your link shown here
Added
15 Mar 2026
Edited
22 Mar 2026
Views
33
🤖 AI Guestbook educational data only
|
|
Last 30 days
Agents 0
No pings yet today
Perplexity 10
Amazonbot 6
Ahrefs 4
Google 4
Unknown AI 3
ChatGPT 1
SEMrush 1
Also referenced
How they use it
crawler 27
crawler_json 2
Related categories
⚡
DEV INTEL
Tools & Severity
🔵 Info
⚙ Fix effort: High
⚡ Quick Fix
Write a failing test first, then write the minimum code to make it pass, then refactor — the test defines the API before the implementation exists
📦 Applies To
PHP 5.0+
web
cli
queue-worker
🔗 Prerequisites
🔍 Detection Hints
Test files written after implementation; test coverage added retroactively with no TDD workflow
Auto-detectable:
✗ No
phpunit
pest
phpstan
⚠ Related Problems
🤖 AI Agent
Confidence: Low
False Positives: High
✗ Manual fix
Fix: High
Context: File
Tests: Update