Incremental Validation
Test and validate after each component/phase instead of waiting until the end. Catches bugs early when they're cheap to fix, prevents cascade failures.
When to use
- •Building complex systems with multiple components
- •Performance-critical applications where late optimization is expensive
- •Projects with >1 week duration
- •When components depend on each other (Phase N uses Phase N-1)
- •Collaborative projects where others build on your work
When NOT to use
- •Throwaway prototypes
- •Simple scripts with no dependencies
- •When requirements will change drastically
- •Pure research/exploration (validation would slow discovery)
Instructions
Step 1: Define Validation Levels
For each component/phase, specify what "done" means:
## Phase N: [Component Name] ### Validation Checklist: **Correctness:** - [ ] Unit tests pass ([X] tests) - [ ] Edge cases covered (empty input, max size, etc.) - [ ] Error handling verified **Performance:** - [ ] Latency target met: <[X] ns/μs/ms - [ ] Throughput target met: >[Y] ops/sec - [ ] Memory usage: <[Z] KB/MB **Integration:** - [ ] Integrates with Phase [N-1] output - [ ] Provides correct input for Phase [N+1] - [ ] No breaking API changes from plan **Code Quality:** - [ ] No compiler warnings - [ ] Passes linter/formatter - [ ] Documentation updated
Step 2: Validate Immediately After Implementation
Strict rule: Don't start Phase N+1 until Phase N validation passes.
Workflow:
# Implement Phase 1 vim src/module.rs # Validate immediately (don't move on!) cargo test --lib module::tests # Unit tests cargo bench --bench module_bench # Performance cargo clippy # Linting # Only if ALL pass: git commit -m "Phase 1: Module complete and validated" # Now start Phase 2
Step 3: Create Fast Feedback Loop
Optimize for speed of validation:
Fast validation (seconds):
# Unit tests only (no integration) cargo test --lib module::tests # Specific test cargo test test_name # Compile check cargo check
Medium validation (minutes):
# All tests cargo test # Benchmarks (quick) cargo bench --bench module -- --quick
Slow validation (hours - run overnight/CI):
# Stress tests cargo test --release -- --ignored --nocapture # Full benchmark suite cargo bench # Integration tests cargo test --test '*'
Step 4: Fix Issues Before Proceeding
If validation fails:
- •Stop - Don't continue to next phase
- •Diagnose - Understand root cause
- •Fix - Correct the issue
- •Re-validate - Run validation again
- •Document - Note what was fixed and why
Anti-pattern:
Phase 1 fails validation → "I'll fix it later" Phase 2 builds on broken Phase 1 Phase 3 builds on broken Phase 2 [Weeks later: Massive refactoring needed]
Correct pattern:
Phase 1 fails validation → Fix immediately Phase 1 passes → Proceed to Phase 2 Phase 2 uses validated Phase 1 Phase 3 uses validated Phase 2 [Result: Solid foundation, no surprises]
Step 5: Document Validation Results
After each phase, record:
## Phase N Validation Results **Tests:** ✅ 15/15 passing **Performance:** ✅ 32ns mean (target: <50ns) **Issues found:** 1 (Transaction size alignment) **Issues fixed:** Array padding added, tests now pass **Time to validate:** 5 minutes **Time to fix issues:** 15 minutes **Lessons learned:** - Rust's default struct layout != expected - Added compile-time assertion to catch early
Best Practices
✅ Do
- •Test immediately - Within seconds of writing code
- •Fix before proceeding - No moving on with broken code
- •Automate validation - Scripts, make targets, CI
- •Document issues - What broke, why, how fixed
- •Celebrate green tests - Positive reinforcement
- •Use watch mode -
cargo watch -x testfor instant feedback
❌ Don't
- •Don't defer testing - "I'll test it all at the end"
- •Don't skip on time pressure - Testing saves time overall
- •Don't ignore flaky tests - Fix or remove them
- •Don't validate too broadly - Test specific component, not everything
- •Don't over-validate - Match validation depth to component risk
Validation Strategy by Component Type
Core Data Structures
Validation: - Size/alignment assertions (compile-time) - Serialization round-trip - Edge cases (empty, max size) - Memory leaks (valgrind/asan) Priority: HIGH (everything builds on this)
Lock-Free Algorithms
Validation: - Unit tests (basic correctness) - Loom tests (concurrency model checking) - Property tests (invariants) - Stress tests (1M+ operations) Priority: CRITICAL (subtle bugs hard to find later)
Business Logic
Validation: - Unit tests (all branches) - Integration tests (with dependencies) - Error cases Priority: MEDIUM (bugs obvious in manual testing)
Performance-Critical Code
Validation: - Benchmarks (P50, P99 latency) - Profiling (flamegraph) - Cache miss rate (perf stat) Priority: HIGH (late optimization expensive)
Common Pitfalls
Pitfall 1: "I'll test it all at the end"
Problem:
- •Build 10 components
- •Test at end
- •Find bug in Component 1
- •All 9 other components built on broken foundation
- •Result: Days/weeks of refactoring
Solution: Test Component 1 immediately, validate before building Component 2
Pitfall 2: Validation too slow
Problem:
- •Full test suite takes 10 minutes
- •Run after every small change
- •Result: 80% of time waiting for tests
Solution:
# Fast: Test only what you changed cargo test --lib module::specific_test # <1 second # Medium: Full unit tests cargo test --lib # ~10 seconds # Slow: Everything cargo test # 10 minutes - run before commit only
Pitfall 3: Ignoring performance until end
Problem:
- •Build entire system
- •Test functionality - all passes ✅
- •Measure performance - 10x too slow ❌
- •Result: No idea where bottleneck is, massive profiling effort
Solution: Benchmark each component as built:
Phase 2: Ring Buffer - Target: <50ns per push/pop - Measured: 4ns ✅ - Proceed to Phase 3 Phase 3: Order Book - Target: <200ns per update - Measured: 3ns ✅ - Proceed to Phase 4
Related skills
- •plan-first-development - Define what to validate per phase
- •parallel-subagent-orchestration - Run validations in parallel
- •multi-level-testing - Different test types for validation
Skill Version: 1.0 Last Updated: 2025-01-06