| name | tester |
| description | Test authoring and test-strategy skill. Activate when writing new tests, planning a test strategy, enumerating edge cases for a feature, or reviewing whether a change has adequate coverage. Optimised for high-signal tests that catch regressions, not coverage theatre. |
| license | Apache-2.0 |
| allowed-tools | ["Read","Write","Edit","Bash","Grep","Glob"] |
| user-invocable | true |
| metadata | {"provenance":{"canonical":"https://github.com/hcross/crewrig","feedback":"https://github.com/hcross/crewrig","version":"1.1.0"}} |
Tester
Tests exist to catch regressions and to document behaviour, not to
inflate a coverage number. Bias toward fewer, sharper tests.
When to activate
- A feature is being added and the project's convention requires tests.
- A bug fix lacks a regression test.
- The user asks for a test plan or edge-case enumeration.
- A diff is up for review and you suspect under-tested behaviour.
If the project has no test infrastructure and the user has not asked
for one, do not invent one — say so and move on.
Operating mode
1. Identify the unit of behaviour
Pick the smallest observable behaviour to test, not the smallest
function. A function with no observable contract has nothing to
test. A file-level helper called only from one place is best tested
through the caller.
2. Golden path + edge cases (not exhaustively)
For each behaviour, plan:
- One golden-path test that exercises the success case.
- One or two edge-case tests for the failure modes that matter.
- A regression test if the test was triggered by a bug fix —
named so it is obvious which bug it guards.
Edge cases to consider, in this order of priority:
- Empty / null / zero-length input.
- Boundary values (off-by-one, overflow, encoding edges).
- Known-bad input (malformed, adversarial — see security skill).
- Concurrent / repeated invocations if the surface is stateful.
- Partial failure (network mid-call, disk full, signal interrupt).
Stop adding cases when the marginal case becomes contrived. Coverage
of contrived cases costs maintenance forever.
3. Real dependencies where it matters
For integration tests:
- Hit a real database when the project's convention is integration
testing (use Testcontainers, Docker Compose, or the project's
scaffold). Mocked DB tests have a known failure mode where they
pass while the real schema is broken.
- Mock an external API only when its calls are non-deterministic, slow,
or rate-limited. Otherwise prefer a recorded fixture (VCR-style).
If the project has explicit guidance ("don't mock the database"),
follow it without rediscovering the lesson.
4. Test naming and structure
Name tests by behaviour, not by function:
✓ test_login_with_valid_credentials_returns_session_token
✗ test_login_function
Structure each test as arrange / act / assert, with a blank line
between each phase. Multi-assertion tests are fine when the assertions
together describe one behaviour; split when they describe two.
5. Verifying a fix
When the trigger is a bug fix:
- Write the test first. Run it. Confirm it fails for the right
reason — not a setup error.
- Apply the fix.
- Run the test. Confirm it passes.
- Run the rest of the suite to detect regressions in unrelated areas.
A test that never failed before the fix proves nothing.
Output expectations
- Tests committed alongside the change they cover, never in a separate
PR (unless the project explicitly batches test PRs).
- A one-line comment above each test stating the why — the behaviour
being asserted — only when the test name alone is not self-evident.
- Test data inline when small; in fixtures when reused or large.
Friction reporting
When a recognition signal fires (see config/TOOLS.md →
Friction Reporting → Recognition signals), invoke the
harness-report skill rather than reimplementing the protocol
inline. The reporter walks you through identifying the offender,
picking the room, and filling the payload.