Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Correctness, Testing, and Evolution

Software isn’t a static thing. It changes constantly: new features arrive, bugs get fixed, requirements shift, and the world it operates in evolves. The patterns in this section live at the tactical level. They address how you know your software is correct, how you keep it correct as it changes, and how you detect when something goes wrong.

Correctness starts with knowing what “right” looks like. An Invariant is a condition that must always hold. A Test is an executable claim about behavior. A Test Oracle tells you whether the output you got is the output you should have gotten. Around every test sits a Harness, the machinery that runs it, and within that harness, Fixtures provide the controlled data and environment the test needs.

Testing isn’t just verification; it can drive design itself. Test-Driven Development uses tests as a design tool, and Red/Green TDD gives that idea a tight, repeatable loop. Once tests pass, Refactoring lets you improve internal structure without breaking what works. When something does break unexpectedly, that’s a Regression, and catching regressions early is one of the highest-value activities in software development.

Not all problems announce themselves. Observability is the degree to which you can see what’s happening inside a running system, and Logging is the primary mechanism for achieving it. Every system has Failure Modes, specific ways it can break, and the most dangerous are Silent Failures, where something goes wrong and nobody notices. Finally, every system operates within a Performance Envelope, the range of conditions under which it still behaves acceptably.

In an agentic coding world, where AI agents generate and modify code at high speed, these patterns become guardrails. An agent can write a function in seconds, but only tests can tell you whether that function does what it should. The faster you change code, the more you need the safety net these patterns provide.

This section contains the following patterns:

  • Invariant — A condition that must remain true for the system to be valid.
  • Test — An executable claim about behavior.
  • Test Oracle — The source of truth that tells you whether an output is correct.
  • Harness — The surrounding machinery used to exercise software in a controlled way.
  • Fixture — The fixed setup, data, or environment used by a test or harness.
  • Test-Driven Development — Tests written to define expected behavior before or alongside implementation.
  • Red/Green TDD — The core TDD loop: write a failing test, then make it pass.
  • Refactor — Changing internal structure without changing external behavior.
  • Regression — A previously working behavior that stops working after a change.
  • Observability — The degree to which you can infer internal state from outputs.
  • Failure Mode — A specific way a system can break or degrade.
  • Silent Failure — A failure that produces no clear signal.
  • Performance Envelope — The range of operating conditions within which a system remains acceptable.
  • Logging — Record what your software does as it runs, so you can understand its behavior after the fact.
  • Happy Path — The default scenario where everything works as expected, and the concept that makes every other kind of testing meaningful.