1. RED Phase
├─ Write failing test
├─ Test defines requirement
├─ Code doesn't exist yet
└─ Test fails with clear error
2. GREEN Phase
├─ Write minimal code to pass
├─ Don't over-engineer
├─ Focus on making test pass
└─ Test now passes
3. REFACTOR Phase
├─ Improve code quality
├─ Extract functions/classes
├─ Optimize performance
├─ Keep tests passing
└─ No test modification
4. Repeat for next requirement
Test First Validation Rules
MANDATORY (STRICT Mode):
Rule T1: Every feature must have tests
├─ Tests must exist BEFORE implementation
├─ Test file created: days 1-2
├─ Code implementation: days 3-5
└─ No exception: 100% coverage required
Rule T2: Coverage ≥ 85% (November 2025 Enterprise)
├─ Unit test coverage >= 85%
├─ Branch coverage >= 80%
├─ Critical paths: 100%
└─ Verified via: coverage.py + codecov
Rule T3: All tests must pass
├─ CI/CD blocks merge on failed tests
├─ No skipped tests in main branch
├─ Flaky tests must be fixed
└─ Test stability: 99.9%
Rule T4: Test quality equals code quality
├─ Tests are documentation
├─ No copy-paste tests
├─ Clear test names
├─ One assertion per concept
└─ DRY (Don't Repeat Yourself)
Example: Test First in Action
# Day 1: Write failing test (RED)deftest_password_hashing_creates_unique_hashes():
"""
Requirement: Each password hash must be unique (different salt)
Expected: Two calls with same password produce different hashes
This test will fail because function doesn't exist yet
"""
hash1 = hash_password("TestPass123")
hash2 = hash_password("TestPass123")
assert hash1 != hash2, "Hashes must be unique"# OUTPUT: NameError: hash_password not defined ✓ Expected# Days 2-3: Write minimal code (GREEN)defhash_password(plaintext: str) -> str:
"""Hash password using bcrypt"""
salt = bcrypt.gensalt(rounds=12)
return bcrypt.hashpw(plaintext.encode('utf-8'), salt).decode('utf-8')
# OUTPUT: Test passes ✓# Days 4-5: Refactor for qualitydefhash_password(plaintext: str) -> str:
"""
Hash password using bcrypt with enterprise security settings
Security:
- Uses bcrypt algorithm (OWASP recommended)
- Salt rounds: 12 (industry standard 2025)
- Auto-unique salt per call
- Non-reversible hash
Performance: ~100ms per hash (acceptable for auth)
"""# Increased from 10 to 12 for 2025 security standards
BCRYPT_ROUNDS = 12
salt = bcrypt.gensalt(rounds=BCRYPT_ROUNDS)
hashed = bcrypt.hashpw(plaintext.encode('utf-8'), salt)
return hashed.decode('utf-8')
# OUTPUT: Test still passes, code is better ✓
Principle 2: Readable (R)
Definition
Code is read more often than written. Prioritize clarity and comprehension over cleverness.
Readability Metrics (November 2025)
Metric
Target
Tool
Threshold
Cyclomatic Complexity
≤ 10
pylint
15 max
Function Length
≤ 50 lines
custom
100 line soft limit
Nesting Depth
≤ 3 levels
pylint
5 max
Comment Ratio
15-20%
custom
10-30% range
Variable Names
Self-documenting
pylint
No single-letter (except loops)
Readability Rules
MANDATORY:
Rule R1: Clear naming
├─ Functions: verb_noun pattern (e.g., validate_password)
├─ Variables: noun pattern (e.g., user_count, is_active)
├─ Constants: UPPER_SNAKE_CASE (e.g., MAX_LOGIN_ATTEMPTS)
├─ Classes: PascalCase (e.g., UserAuthentication)
└─ Acronyms: Spell out (e.g., user_identification_number not uin)
Rule R2: Single responsibility principle
├─ One function = one job
├─ One class = one reason to change
├─ Extract complexity
├─ Maximum cyclomatic complexity: 10
└─ If complex: split into smaller functions
Rule R3: Documentation
├─ Function docstrings (every function)
├─ Module docstrings (at file top)
├─ Complex logic: inline comments
├─ Why, not what: explain reasoning
└─ Keep docs in sync with code
Rule R4: Consistent style
├─ Follow PEP 8 (Python)
├─ Use auto-formatter (Black, Prettier)
├─ Configure IDE to enforce style
├─ CI/CD blocks non-compliant commits
└─ Team agreement on conventions
Example: Readability Progression
Before (Unreadable):
deff(x, y):
"""Process data"""if x > 0:
z = []
for i inrange(len(y)):
if y[i] != None:
z.append(y[i] * x)
returnsum(z) / len(z) iflen(z) > 0else0returnNone# Issues:# - Single letter variables (x, y, z)# - No context (what is this?)# - Complex logic without explanation# - Cyclomatic complexity: 5# - 0% documentation
After (Readable):
defcalculate_weighted_average(weight_factor: float, values: List[float]) -> Optional[float]:
"""
Calculate weighted average of values
Uses arithmetic mean with optional weight scaling factor.
Filters out None values automatically.
Args:
weight_factor: Scaling factor (typically 0.0-1.0)
values: List of numeric values to average
Returns:
Weighted average or None if no valid values
Example:
>>> calculate_weighted_average(1.5, [10, 20, 30])
45.0
"""# Early return: invalid weightif weight_factor <= 0:
returnNone# Filter valid values (exclude None)
valid_values = [v for v in values if v isnotNone]
# Handle empty caseifnot valid_values:
returnNone# Calculate weighted average
weighted_sum = sum(v * weight_factor for v in valid_values)
count = len(valid_values)
return weighted_sum / count
Principle 3: Unified (U)
Definition
Consistency breeds confidence. Use unified patterns, conventions, and architectures across the codebase.
# Unified approach across all modulestry:
result = risky_operation()
except SpecificError as e:
logger.error(f"Operation failed: {e}", extra={"user_id": user_id})
raise ApplicationError(f"Failed to complete operation") from e
except Exception as e:
logger.critical(f"Unexpected error: {e}")
raise ApplicationError("Internal error") from e
import logging
logger = logging.getLogger(__name__)
# Consistent across all modules
logger.info(f"User login: {user_email}")
logger.error(f"Login failed: {error}", extra={"user": user_id})
logger.debug(f"Password hash comparison took {elapsed_ms}ms")
Unified Validation
Rules (STRICT Mode):
Rule U1: Consistent file structure
├─ All modules follow same layout
├─ Imports, docstrings, classes, functions
├─ Private helpers at bottom
└─ Enforce via: pylint plugin + CI/CD
Rule U2: Consistent naming across codebase
├─ Same concept = same name (user_id everywhere)
├─ No aliases (don't use both user_id and uid)
├─ Consistent abbreviations (req not rq)
└─ Enforce via: code review + linter config
Rule U3: Consistent error handling
├─ Same exception types for same errors
├─ Same logging approach everywhere
├─ Same response format for APIs
└─ Enforce via: custom exceptions + base classes
Rule U4: Consistent testing patterns
├─ Same test structure (setup/execute/verify)
├─ Same naming (test_xxx_with_yyy_expects_zzz)
├─ Same fixtures for common objects
└─ Enforce via: pytest plugins
Principle 4: Secured (S)
Definition
Security is not an afterthought. Build security into design from day one following OWASP standards.
OWASP Top 10 (2024 Enterprise Edition)
MoAI-ADK enforces all 10 OWASP Top 10 vulnerabilities prevention: