7.2 KiB
tdd-implement
Implement minimal code to make failing tests pass - the "Green" phase of TDD.
Purpose
Write the simplest possible implementation that makes all failing tests pass. This is the "Green" phase of TDD where we focus on making tests pass with minimal, clean code.
Prerequisites
- Story has failing tests (tdd.status: red)
- All tests fail for correct reasons (missing implementation, not bugs)
- Test runner is configured and working
- Dev agent has reviewed failing tests and acceptance criteria
Inputs
required:
- story_id: '{epic}.{story}' # e.g., "1.3"
- story_path: '{devStoryLocation}/{epic}.{story}.*.md' # Path from core-config.yaml
- failing_tests: # List from story TDD metadata
- id: test identifier
- file_path: path to test file
- status: failing
Process
1. Review Failing Tests
Before writing any code:
- Read each failing test to understand expected behavior
- Identify the interfaces/classes/functions that need to be created
- Note expected inputs, outputs, and error conditions
- Understand the test's mocking strategy
2. Design Minimal Implementation
TDD Green Phase Principles:
- Make it work first, then make it right
- Simplest thing that could possibly work
- No feature without a failing test
- Avoid premature abstraction
- Prefer duplication over wrong abstraction
3. Implement Code
Implementation Strategy:
approach: 1. Start with simplest happy path test
2. Write minimal code to pass that test
3. Run tests frequently (after each small change)
4. Move to next failing test
5. Repeat until all tests pass
avoid:
- Adding features not covered by tests
- Complex algorithms when simple ones suffice
- Premature optimization
- Over-engineering the solution
Example Implementation Progression:
// First test: should return user with id
// Minimal implementation:
function createUser(userData) {
return { id: 1, ...userData };
}
// Second test: should validate email format
// Expand implementation:
function createUser(userData) {
if (!userData.email.includes('@')) {
throw new Error('Invalid email format');
}
return { id: 1, ...userData };
}
4. Run Tests Continuously
Test-Driven Workflow:
- Run specific failing test
- Write minimal code to make it pass
- Run that test again to confirm green
- Run full test suite to ensure no regressions
- Move to next failing test
Test Execution Commands:
# Run specific test file
npm test -- user-service.test.js
pytest tests/unit/test_user_service.py
go test ./services/user_test.go
# Run full test suite
npm test
pytest
go test ./...
5. Handle Edge Cases
Implement only edge cases that have corresponding tests:
- Input validation as tested
- Error conditions as specified in tests
- Boundary conditions covered by tests
- Nothing more, nothing less
6. Maintain Test-Code Traceability
Commit Strategy:
git add tests/ src/
git commit -m "GREEN: Implement user creation [UC-001, UC-002]"
Link implementation to specific test IDs in commits for traceability.
7. Update Story Metadata
Update TDD status to green:
tdd:
status: green
cycle: 1
tests:
- id: 'UC-001'
name: 'should create user with valid email'
type: unit
status: passing
file_path: 'tests/unit/user-service.test.js'
- id: 'UC-002'
name: 'should reject user with invalid email'
type: unit
status: passing
file_path: 'tests/unit/user-service.test.js'
Output Requirements
1. Working Implementation
Create source files that:
- Make all failing tests pass
- Follow project coding standards
- Are minimal and focused
- Have clear, intention-revealing names
2. Test Execution Report
Running tests...
✅ UserService > should create user with valid email
✅ UserService > should reject user with invalid email
2 passing, 0 failing
3. Story File Updates
Append to TDD section:
## TDD Progress
### Green Phase - Cycle 1
**Date:** {current_date}
**Agent:** James (Dev Agent)
**Implementation Summary:**
- Created UserService class with create() method
- Added email validation for @ symbol
- All tests now passing ✅
**Files Modified:**
- src/services/user-service.js (created)
**Test Results:**
- UC-001: should create user with valid email (PASSING ✅)
- UC-002: should reject user with invalid email (PASSING ✅)
**Next Step:** Review implementation for refactoring opportunities
Implementation Guidelines
Code Quality Standards
During Green Phase:
- Readable: Clear variable and function names
- Simple: Avoid complex logic when simple works
- Testable: Code structure supports the tests
- Focused: Each function has single responsibility
Acceptable Technical Debt (to be addressed in Refactor phase):
- Code duplication if it keeps tests green
- Hardcoded values if they make tests pass
- Simple algorithms even if inefficient
- Minimal error handling beyond what tests require
Common Patterns
Factory Functions:
function createUser(data) {
// Minimal validation
return { id: generateId(), ...data };
}
Error Handling:
function validateEmail(email) {
if (!email.includes('@')) {
throw new Error('Invalid email');
}
}
State Management:
class UserService {
constructor(database) {
this.db = database; // Accept injected dependency
}
}
Error Handling
If tests still fail after implementation:
- Review test expectations vs actual implementation
- Check for typos in function/method names
- Verify correct imports/exports
- Ensure proper handling of async operations
If tests pass unexpectedly without changes:
- Implementation might already exist
- Test might be incorrect
- Review git status for unexpected changes
If new tests start failing:
- Implementation may have broken existing functionality
- Review change impact
- Fix regressions before continuing
Anti-Patterns to Avoid
Feature Creep:
- Don't implement features without failing tests
- Don't add "obviously needed" functionality
Premature Optimization:
- Don't optimize for performance in green phase
- Focus on correctness first
Over-Engineering:
- Don't add abstraction layers without tests requiring them
- Avoid complex design patterns in initial implementation
Completion Criteria
- All previously failing tests now pass
- No existing tests broken (regression check)
- Implementation is minimal and focused
- Code follows project standards
- Story TDD status updated to 'green'
- Files properly committed with test traceability
- Ready for refactor phase assessment
Validation Commands
# Verify all tests pass
npm test
pytest
go test ./...
mvn test
dotnet test
# Check code quality (basic)
npm run lint
flake8 .
golint ./...
Key Principles
- Make it work: Green tests are the only measure of success
- Keep it simple: Resist urge to make it elegant yet
- One test at a time: Focus on single failing test
- Fast feedback: Run tests frequently during development
- No speculation: Only implement what tests require