Capstone: Designing a Test Strategy for a Real System

Software Testing Strategy

Chapter 10 · Capstone: Designing a Test Strategy for a Real System

One continuous worked project: a full test strategy for Clean Code, SOLID & Refactoring's own refactored TangleMart order system — the exact calculate_order_total, OrderService, DiscountStrategy/ShippingStrategy hierarchies, and payment classes that course's own capstone assembled. Every technique from Chapters 2 through 9 gets applied to this one real system, in the order its own dependencies actually require, closing with a single order run through every layer at once.

Step 1Unit Tests (Chapter 3)

Verified directly — AAA-structured, isolated unit tests for the pricing core
test_gold_discount_applies_ten_percent_off and test_no_discount_applies_full_price each create their own fresh items list — no shared mutable state between them, per Chapter 3's own finding. Both pass: $41.00 with GoldDiscount, $45.00 with NoDiscount.

Step 2Test Doubles (Chapter 4)

Verified directly — a fresh 802x measured speedup from a fake payment method over real file-based I/O
100 checkouts through a real, disk-writing payment method: 181.99ms total. The identical 100 checkouts through FakePayment (a genuine in-memory list): 0.23ms total802× faster, consistent with Chapter 4's own 443x finding on a different dependency. A correctness check confirms the fake genuinely exercises real logic: fake.charges == [41.0] after a $41.00 checkout.

Step 3Integration & Contract Tests (Chapter 5)

Verified directly — a real integration test and a contract test that caught a genuinely broken new strategy
test_integration_real_checkout, wiring OrderService directly to the real CreditCardPayment with no doubles: passes$41.00, correct receipt, inventory correctly decremented. A contract test asserting every DiscountStrategy's apply() returns a non-negative number: NoDiscount, GoldDiscount, PlatinumDiscount all pass; a deliberately broken BrokenDiscount (returning a string instead of a number) is caught immediately"apply() must return a number, got str" — without ever needing to run it through a full checkout.

Step 4End-to-End Testing (Chapter 6)

Verified directly — the exact flakiness finding from Chapter 6, reproduced on TangleMart's own checkout flow
A simulated asynchronous payment-gateway confirmation, checked with a naive fixed 10ms wait: 21/100 runs passed (21.0%) over 100 identical runs. The same flow checked with polling instead of guessing: 100/100 passed (100.0%). The lesson from Chapter 6 wasn't specific to browser automation — any e2e test involving real asynchronous confirmation carries the identical risk.

Step 5Test-Driven Development (Chapter 7)

# RED: calculate_loyalty_points doesn't exist yet - NameError # GREEN: minimal implementation def calculate_loyalty_points(total): return (int(total) // 10) * 10 # 10 points per full $10 spent
Verified directly — a new feature built through three real Red-Green cycles, then refactored with zero behavior change
Cycle 1 ($41.00 → 40 points), Cycle 2 (exactly $10.00 → 10 points), Cycle 3 ($9.99 → 0 points, below the first tier) — all pass. A cleaner refactored implementation, checked against all 5 accumulated cases including two new ones ($100.00 → 100, $0 → 0): all pass. This is exactly the algorithmically well-suited case Chapter 7 identified — a deterministic rule with a knowable-in-advance correct answer.

Step 6Behavior-Driven Development (Chapter 8)

Verified directly — the loyalty-points scenario failed loudly the moment the policy changed
scenario_customer_earns_loyalty_points_on_checkout (Given a $41.00 order, When points are calculated, Then 40 points are earned): passes. Re-run unchanged against a policy bump to 15 points per $10: fails immediately"expected 40, got 60." Exactly Chapter 8's own living-documentation finding, on a feature this capstone built from scratch two steps earlier.

Step 7Testing Legacy Code (Chapter 9)

Verified directly — Chapter 9's own characterization tests, reused directly, verified surviving a real migration into the new architecture
All 6 of Chapter 9's own characterization tests for legacy_calculate_shipping pass against the original function. Wrapped in a new LegacyShippingAdapter(ShippingStrategy) — migrating the old, undocumented function into this capstone's own strategy-pattern architecture — the identical 6 tests: all pass, confirming the migration preserved every discovered quirk (the negative-weight clamp, the expensive unknown-zone default, the bulk discount) exactly.

The Actual Pyramid Shape Built

LevelTests built across Steps 1-7Why this shape
Unit11 (2 pricing + 3 TDD loyalty-points + 6 characterization)Fast, precise fault localization (Chapter 2), the base of the pyramid
Integration / Contract4 (1 real-seam integration + 3 passing contract checks)Catches wiring and interface mismatches Chapters 1 and 4 found unit tests structurally can't
End-to-End1 (the polling-based checkout flow)The one thing that exercises real elapsed time across the whole flow, kept deliberately small per Chapter 1's own 26.1x cost finding
BDD scenario1 (living documentation for the loyalty-points policy)Not a pyramid level — a cross-cutting spec that also happens to be a test
This shape wasn't arbitrary — it's the direct sum of nine chapters' own verified findings
11 unit tests dominate because Chapter 1 measured them running 147,104x faster than e2e tests. Only 1 e2e test exists because Chapter 6 verified even a single ice-cream-cone-shaped test adds real, measurable cost and fault-localization risk. The 4 integration/contract tests exist specifically because Chapters 1, 4, and 5 each found a real bug class no amount of additional unit tests could have caught.

Final Integration: One Real Order, Every Layer

Verified end to end — every value from every prior step matches exactly
A single real order (2× widget, gold discount, standard shipping) run through the fully assembled system: total $41.00, receipt "Charged $41.00 to card", loyalty points 40, inventory correctly decremented to {'widget': 48} — plus a separate legacy-shipping quote for an unrelated package, correctly computed at $6.00 through the migrated adapter. Every number matches what Steps 1 through 7 independently verified, confirming the whole assembled test strategy — not just its individual pieces — describes one coherent, correct system.

Hands-On Exercises

Exercise 1

Add a third unit test for this chapter's own calculate_order_total, covering PlatinumDiscount (20% off) combined with a hypothetical ExpressShipping costing $15. Verify it passes, following the same AAA structure and isolated-state pattern as Step 1's own two tests.

📄 View solution
Exercise 2

Extend Step 3's own contract test to also reject a DiscountStrategy whose apply() returns a total greater than the input (a discount that somehow increases the price). Write a deliberately broken example that triggers this new check, and verify the existing valid strategies (NoDiscount, GoldDiscount, PlatinumDiscount) still pass.

📄 View solution
Exercise 3

Add a second order to this chapter's own final integration check — a different item, PlatinumDiscount, checked out through the same OrderService instance used for the first order — and verify both orders' own totals, receipts, loyalty points, and inventory deductions are correct and fully independent of each other.

📄 View solution

Chapter 10 Quick Reference — Course Summary

  • Verified end to end: a full test pyramid built for one real system — 11 unit, 4 integration/contract, 1 e2e, 1 BDD scenario — every level directly justified by a specific prior chapter's own measured finding
  • Step 2 reproduced Chapter 4's finding: an 802x fake-vs-real-I/O speedup on this system's own payment method
  • Step 3 caught a genuinely broken strategy via a contract test, before it ever reached a full checkout
  • Step 4 reproduced Chapter 6's flakiness finding exactly: 21% pass rate with a fixed wait, 100% with polling
  • Step 5 built a brand-new feature via real TDD, then Step 6 turned its own policy into a living, executable specification
  • Step 7 migrated legacy code into the new architecture with characterization tests proving zero behavior change
  • Course complete: the pyramid, unit tests, test doubles, integration/contract testing, e2e testing, TDD, BDD, and legacy code — all ten chapters, verified throughout