sensing-and-separation
Classify why a dependency is blocking a test and choose the breaking move accordingly.
SKILL.mdsubagents/legacy-code-change-advisor/skills/sensing-and-separation/SKILL.md
GitHubSensing and separation
Purpose
Classify why a dependency is blocking a test and choose the breaking move accordingly. There are two reasons to break a dependency to get code under test: sensing — you cannot access values the code computes — and separation — you cannot get the code into a test harness to run at all (P081). The distinction matters because faking a collaborator is the dominant technique for sensing (P051), while there are many techniques for separation, and the incisions made before tests exist must stay conservative.
When to use
- A class cannot be instantiated in a harness, or its computed effects cannot be observed in a test (P083 — the four common obstacles: hard construction, harness will not build, bad constructor side effects, undetectable side effects).
Do not apply when the code is already isolable and its effects are directly observable — no dependency needs breaking.
Procedure
- State what you are trying to test at the change point.
- Classify the blocker (P081):
- Sensing — the code runs but you cannot observe the value/effect it produces (e.g. it writes to a collaborator instead of returning).
- Separation — the code cannot even be instantiated or run in the harness (e.g. the constructor needs a live database or network; globals and singletons are among the hardest such dependencies, P057). A single dependency can block both; name each reason.
- For sensing → use a fake object (P051). Substitute a fake that impersonates the collaborator so the test can sense effects through it (record the calls/values the code under test sends). Prefer a plain hand-written fake; reach for a mock (a fake that asserts internally) only when you must write many fakes and the language makes hand-writing them costly (P123).
- For separation → make the collaborator fakeable (P137). Introduce a seam at the
blocking collaborator — typically Extract Interface — so the class under test can hold
either the real collaborator or a fake (see
dependency-breaking-techniques,seam-model). For an irritating parameter that is slow, unreliable, or has side effects, extract an interface on it and pass a fake supplying only what the test needs (P139). - Make the incision conservatively. Before any tests exist, make minimal, signature-preserving changes only — even if the code temporarily looks worse. Accept the "scar"; heal it once tests cover the area. Do not bundle cleanup with the break.
- Verify the code now instantiates and its effects are observable, then proceed to characterization tests.
Inputs
- The code unit, the change point, and the blocking collaborator(s)/dependencies.
- The language in use (affects which seam/break techniques apply).
Output
For each blocking dependency: its reason class (sensing / separation / both), the breaking technique to apply (fake object, Extract Interface, …), and a note that the pre-test incision must stay conservative and signature-preserving.
References
dependency-breaking-techniques— the Extract Interface and fake-object technique detail.seam-model— where and how to insert the substitution point.characterization-testing— what to do once the code is in the harness.
Provenance
Derived from principles P081 (sensing vs separation), P051 (fake objects), P123 (fake vs mock), P137 (make a collaborator fakeable), P139 (irritating parameter), P057 (globals / singletons), and P083 (harness obstacles). Source is distillation-only; paraphrased, not quoted.