testinglisted
Install: claude install-skill dean0x/devflow
# Testing Patterns
## Iron Law
> **TESTS VALIDATE BEHAVIOR, NOT IMPLEMENTATION** [4][8]
>
> A test should fail when behavior breaks, not when implementation changes. Mock at
> boundaries, not internals. Test the contract, not the code path. If tests are hard to
> write, the design is wrong — fix the architecture, not the tests. [3][8]
---
## Testing Shapes [6][7][10]
| Shape | Guidance |
|-------|---------|
| Pyramid [6] | Many unit → fewer integration → fewest E2E |
| Trophy [7] | Integration tests give best ROI for UI-heavy code |
| Google [4] | 70% unit / 20% integration / 10% E2E; avoid E2E excess [12] |
---
## Test Doubles Taxonomy [1][9]
| Type | When to Use | Example |
|------|------------|---------|
| **Dummy** | Fill unused parameters | `null`, empty object |
| **Stub** | Return canned data, no assertions | `getRate: () => 0.1` |
| **Spy** | Record calls, assert after | `jest.spyOn()` on public methods |
| **Mock** | Pre-programmed expectations | `expect(fn).toHaveBeenCalledWith(x)` |
| **Fake** | Working substitute (in-memory DB) | `InMemoryUserRepo` |
"Mock roles, not objects" — mock interfaces you own, never third-party internals [3][9].
---
## Test Design Red Flags
| Red Flag | Symptom | Root Cause | Fix |
|----------|---------|-----------|-----|
| Complex setup >10 lines [8] | `beforeEach` with 6+ mocks | Too many dependencies | Split service; use fakes [1][4] |
| Repetitive try/catch [8] | Same pattern >3 times | API throws, not Result | Migrate to