Installs into .claude/skills of the current project.
Are you the author of Test Strategy?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/dev-toolbelt-test-strategy)
---
name: test-strategy
description: Testing strategy — what, when, how; coverage planning.
---
# Test Strategy
## The Testing Decision Framework
Before writing a test, ask:
1. **What could break here?** — If nothing can break, don't test it.
2. **How often will this break?** — High-risk logic needs tests. Config files don't.
3. **How hard is it to detect if broken?** — Silent failures need tests. Runtime errors are visible.
4. **What's the cost of a bug here?** — Payment flows need tests. Admin labels might not.
5. **Is this test maintainable?** — Tests that break on every refactor have negative ROI.
---
## Test Pyramid
```
/\
/ \ E2E Tests
/ \ (few, slow, high confidence)
/------\
/ \ Integration Tests
/ \ (moderate, medium speed)
/------------\
/ \ Unit Tests
/ \ (many, fast, focused)
/------------------\
```
### Unit Tests
- Test a single function/method in isolation
- **No database, no network, no filesystem, no external API or storage — ever, including test/staging instances.** Inject and mock any such dependency; see the Hard rule in `skills/testing/test-pyramid/SKILL.md`
- Fast: < 10ms each
- Write when: pure business logic, complex algorithms, edge cases in a function
### Integration Tests
- Test how components work together
- May use real database (test DB), real filesystem
- Medium speed: < 1s each
- Write when: service + repository interaction, API request/response cycle, database queries
### E2E Tests
- Test the full user flow through the application
- Runs against a real (or staging) environment
- Slow: seconds to minutes
- Write when: critical user journeys, checkout flows, authentication, core business flows
- Keep minimal — prefer integration tests where possible
---
## Avoid Overengineering Tests
**Do not write tests for:**
- Framework behavior (the framework is already tested)
- Trivial getters/setters with no logic
- Configuration files
- Auto-generated code
- Code that's about to be deleted
**Watch out for:**
- Tests that test implementation details (brittle — breaks on refactor)
- Tests that duplicate the source code logic
- Tests that require extensive mocking just to run (signals the code is hard to test)
- 100% coverage as a goal — coverage measures lines executed, not quality
---
## Testing Testable Code
Code is testable when:
- Dependencies are injected, not instantiated inside
- Functions are pure (same input → same output)
- Side effects are isolated (no mixing DB queries with business logic)
- Classes are small and focused (one responsibility)
When writing production code, prefer patterns that make testing natural — but don't over-engineer the production code just to reach testability.
---
## Coverage Targets by Context
| Context | Coverage Target |
|---------|----------------|
| Business logic / domain layer | 80–90% |
| API controllers | 70–80% (integration level) |
| Infrastructure / repositories | 60–70% |
| UI components | Key paths only |
| Overall | 60–70% is usually healthy |
These are guidelines, not mandates. A 40%-covered codebase with tests on the right things beats a 90%-covered one with tests on the wrong things.
---
## Test Naming Convention
Tests should read like specifications. Use camelCase — no underscores:
```
given[Context]When[Action]Then[ExpectedResult]
// or simply:
[methodOrFeature][Scenario][ExpectedOutcome]
Examples:
- calculateDiscountWithVIPCustomerApplies15Percent
- createOrderWithOutOfStockItemThrowsUnavailableException
- loginEndpointWithWrongPasswordReturns401
```
---
## AAA Pattern
Every test follows Arrange → Act → Assert:
```
// Arrange — set up the test scenario
// Act — execute the behavior under test
// Assert — verify the outcome
```
---
## Verify the New File Lands Where the Runner Looks
Before finishing, check the new test's path against the runner's actual `include`/`testMatch` config (`vitest.config.*`, `jest.config.*`, `phpunit.xml`, etc.), not just the project's stated convention. A test placed outside that glob (e.g. colocated under `src/` when the runner only scans `tests/`) passes silently by never running — it reports success while covering nothing. Run the scoped command from `skills/shared/scoped-test-execution/SKILL.md` against the new file specifically and confirm it was actually picked up, not skipped.
Add these as comments in tests where the sections aren't obvious.