Tiered TDD Workflow
Renacer follows a tiered testing workflow inspired by the Trueno project, optimizing for rapid TDD cycles while maintaining comprehensive test coverage.
Philosophy
Not all tests are equal in execution time. Tiered TDD separates tests into three tiers based on speed, allowing developers to run appropriate test suites for different workflows.
Key Principle: Run the fastest tests frequently, slower tests less often.
Three Tiers
Tier 1: Fast Tests (<5 seconds)
Purpose: Immediate feedback during development
Includes:
- Unit tests
- Property-based tests (proptest)
- Doctests
- Quick integration tests
When to Run:
- After every code change
- Before committing
- During RED-GREEN-REFACTOR cycle
# Run Tier 1 tests
make test-tier1
# Or manually
cargo test --lib # Unit tests
cargo test --doc # Doctests
Example output:
running 97 tests
test result: ok. 97 passed; 0 failed; 0 ignored; 0 measured
Duration: 2.3s ✅
Tier 2: Medium Tests (<30 seconds)
Purpose: Comprehensive integration testing
Includes:
- All integration tests
- Full syscall filtering tests
- Multi-process tracing tests
- End-to-end feature tests
When to Run:
- Before pushing to remote
- During code review
- After completing a feature
# Run Tier 2 tests
make test-tier2
# Or manually
cargo test --tests # All integration tests
Example output:
running 51 integration tests
test result: ok. 51 passed; 0 failed; 0 ignored
Duration: 24.7s ✅
Tier 3: Slow Tests (<5 minutes)
Purpose: Exhaustive quality validation
Includes:
- Fuzz testing (short runs)
- Mutation testing
- Long-running stress tests
- Performance benchmarks
- Coverage analysis
When to Run:
- Before merging to main
- During release preparation
- Weekly on CI/CD
- Sprint completion
# Run Tier 3 tests
make test-tier3
# Or manually
cargo fuzz run filter_parser -- -max_total_time=60 # 1 minute fuzz
cargo mutants --in-place -t 180 # 3 minute timeout per mutant
Example output:
Fuzz tests: 15,347 runs in 60s ✅
Mutation tests: 12/15 mutants caught (80%) ✅
Duration: 4m 32s ✅
Makefile Targets (Sprint 29)
Configuration
# Tiered TDD targets following trueno pattern
.PHONY: test-tier1 test-tier2 test-tier3
# Tier 1: Fast unit tests (<5s)
test-tier1:
@echo "🔬 Tier 1: Fast tests (<5s)"
@time cargo test --lib
@time cargo test --doc
# Tier 2: Integration tests (<30s)
test-tier2:
@echo "🔧 Tier 2: Integration tests (<30s)"
@time cargo test --tests
# Tier 3: Fuzz + mutation (<5m)
test-tier3:
@echo "🚀 Tier 3: Fuzz + mutation (<5m)"
@time cargo fuzz run filter_parser -- -max_total_time=60 || true
@time cargo mutants --in-place -t 180 || true
Workflow Examples
Example 1: Feature Development (RED-GREEN-REFACTOR)
# RED: Write failing test
vim src/filter.rs # Add test_new_filter_feature
# Run Tier 1 (fast feedback)
make test-tier1
# ❌ FAIL: test_new_filter_feature
# GREEN: Implement feature
vim src/filter.rs # Implement feature
# Run Tier 1 again
make test-tier1
# ✅ PASS: All 98 tests
# REFACTOR: Improve code
vim src/filter.rs # Extract helper function
# Run Tier 1 to ensure no regressions
make test-tier1
# ✅ PASS: All 98 tests
# Before commit: Run Tier 2
make test-tier2
# ✅ PASS: All 149 tests
# Commit
git commit -m "feat: Add new filter feature"
Example 2: Pre-Push Validation
# Run all tiers before pushing
make test-tier1 && make test-tier2 && make test-tier3
# Or use convenience target
make test-all # Runs tier1, tier2, tier3 sequentially
Example 3: Sprint Completion
# Full validation before sprint completion
make test-all
make coverage
pmat analyze complexity
pmat validate-tdg
# If all pass ✅, sprint complete!
Integration with Pre-Commit Hooks
Pre-commit hooks use Tier 1 + selective Tier 2:
# .git/hooks/pre-commit (simplified)
#!/bin/bash
echo "🔬 Running Tier 1 tests..."
make test-tier1 || exit 1
echo "🔧 Running critical Tier 2 tests..."
cargo test --test core_functionality || exit 1
echo "✅ Tests passed, committing..."
CI/CD Integration
GitHub Actions Example
name: Tiered Testing
on: [push, pull_request]
jobs:
tier1:
name: Tier 1 (Fast)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Run Tier 1 tests
run: make test-tier1
timeout-minutes: 1
tier2:
name: Tier 2 (Integration)
runs-on: ubuntu-latest
needs: tier1
steps:
- uses: actions/checkout@v2
- name: Run Tier 2 tests
run: make test-tier2
timeout-minutes: 5
tier3:
name: Tier 3 (Exhaustive)
runs-on: ubuntu-latest
needs: tier2
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v2
- name: Run Tier 3 tests
run: make test-tier3
timeout-minutes: 10
Performance Targets
| Tier | Target Time | Actual (v0.4.1) | Status |
|---|---|---|---|
| Tier 1 | <5s | 2.3s | ✅ |
| Tier 2 | <30s | 24.7s | ✅ |
| Tier 3 | <5m | 4m 32s | ✅ |
Test Categorization Guidelines
Tier 1 Criteria:
- No external dependencies (files, network)
- No subprocess spawning
- No sleep/delays
- Pure computation tests
Tier 2 Criteria:
- May spawn processes
- May create temporary files
- May use realistic test programs
- Should clean up resources
Tier 3 Criteria:
- Long-running by nature (fuzz, mutation)
- Performance-sensitive
- Resource-intensive
- Optional on developer machines
Benefits
-
Faster Development Cycles
- Tier 1 provides instant feedback (2-5s)
- No waiting for slow tests during TDD
-
Efficient CI/CD
- Fail fast on Tier 1 (saves CI minutes)
- Only run Tier 3 on main branch
-
Developer Experience
- Clear expectations for test duration
- No surprise 10-minute test runs
-
Comprehensive Coverage
- All tests still run before merge
- No quality sacrificed for speed
Monitoring Test Performance
Track test duration over time:
# Measure Tier 1 performance
time make test-tier1
# Identify slow tests
cargo test --lib -- --report-time
# If Tier 1 exceeds 5s, investigate:
# - Are integration tests in unit test files?
# - Are there unnecessary sleeps?
# - Can tests be parallelized better?
Future Enhancements
Planned improvements:
- Tier 0: Compile-only checks (<1s)
- Tier 4: Extended fuzz runs (1 hour+)
- Smart Test Selection: Only run affected tiers based on changes
- Parallel Tier Execution: Run Tier 1 and Tier 2 concurrently
Related Patterns
Renacer's tiered TDD is inspired by:
- Trueno: Original tiered testing pattern
- Google Testing Blog: Test sizes (small/medium/large)
- Bazel: Test tags for selective execution
- pytest: Markers for test categorization