Observable behavior is the externally detectable functionality or state that helps a client achieve a goal. Tests should verify what the system produces, not how it produces it. section 5.2 section 5.5
Observable behavior and implementation details form a separate dimension from public and private APIs. A public method can still expose an implementation detail, while private code can occasionally implement a non-public contract. section 5.2 section 11.8
Treat code as observable behavior when it does either of the following:
- Expose an operation that helps the client achieve a goal, such as performing a calculation or causing a side effect. section 5.5
- Expose state that helps the client achieve a goal, such as information that production code uses to determine an outcome. section 5.5
- Keep implementation details private so the public API coincides with the behavior clients actually need. section 5.2
Normalize names without leaking the mechanism
A User class initially exposes NormalizeName, allowing clients and tests to depend on trimming and length limits directly. Moving normalization into the Name setter preserves the observable outcome while hiding the implementation detail.
Test the discount, not the status field
Customer.Promote changes private status from Regular to Preferred, but production code observes only the resulting discount. Test no discount before promotion and a 5% discount afterward. section 11.2
Extract complex hidden logic
When a private price calculation is too complex to test through Order’s observable behavior, extract it into PriceCalculator rather than making GetPrice public. section 11.1
Use observable behavior as a black-box boundary: test private methods and state indirectly, avoid granting tests special privileges, and widen the public API only when clients genuinely need the operation or state. section 11.1 section 11.8



