en un clic
contract-testing
Use when writing tests for any interface, abstract base class, or type with multiple implementations.
Menu
Use when writing tests for any interface, abstract base class, or type with multiple implementations.
Use when adding new classes, refactoring code, or reviewing PRs for Particle-Viewer.
Use when a task needs design exploration before any implementation begins. Required for any task with unclear approach, significant architecture impact, or multiple valid solutions.
Use when building, adding dependencies, configuring CMake options, troubleshooting build failures, or managing Flatpak packaging for Particle-Viewer.
Use when writing or reviewing C++ code, running pre-commit checks, or addressing formatting, naming, or static analysis violations.
Use when implementing C++ code for Particle-Viewer, handling GL resources, working with SDL3, or applying DRY/deprecation/docs-commit patterns.
Use when writing or reviewing any C++ class that owns resources, has a destructor, or acquires in a constructor.
| name | contract-testing |
| license | MIT |
| description | Use when writing tests for any interface, abstract base class, or type with multiple implementations. |
EVERY ABSTRACT TYPE REQUIRES A CONTRACT TEST FIXTURE
YOU MUST write a contract test fixture before shipping any interface with multiple implementations. No exceptions.
Violating the letter of this rule is violating the spirit of this rule.
Announce at start: "I am using the contract-testing skill to write contract tests for [interface]."
[+] All met -> proceed [-] Any unmet -> write the contract test fixture before adding any new implementation
A contract test describes the behavioral invariants all implementations must satisfy. Violating a contract test violates the Liskov Substitution Principle.
Use TYPED_TEST_P -- not TEST_F -- because TEST_F instantiates the fixture class directly and will not compile against a pure-virtual base. See references/CONTRACT_TESTING.md for the full TYPED_TEST_P / INSTANTIATE_TYPED_TEST_SUITE_P pattern.
A failing contract test means the hierarchy is wrong -- fix the hierarchy, not the test.
| Excuse | Reality |
|---|---|
| "Integration tests cover the contract" | Integration tests verify composition, not behavioral invariants. |
| "There is only one implementation" | Write the fixture now. A second implementation arrives later. |
| "The interface is simple, nothing to test" | Simple interfaces still have invariants (no-throw, non-null return). |
| "The mock already tests the behavior" | Mocks verify interactions, not behavioral contracts. Both are needed. |
| "The contract test is redundant -- the implementations are clearly equivalent" | Equivalence is an assumption, not evidence. Contract tests document and enforce invariants across all current and future implementations. |
TEST_F instead of TYPED_TEST_P -- STOP. TEST_F instantiates the concrete fixture directly; it does not test behavioral invariants across implementations.testing -- parent skill; Test Doubles taxonomy, saw-the-test-fail gate, AAA namingoop-principles -- sibling; contract tests enforce Liskov Substitutionarchitecture-review -- sibling; interfaces also need layer boundary review