@dennisrongo/skills 0.6.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -0
- package/package.json +1 -1
- package/skills/_template/SKILL.md +8 -0
- package/skills/api-contract-review/SKILL.md +67 -0
- package/skills/code-review/SKILL.md +25 -4
- package/skills/codebase-explainer/SKILL.md +13 -6
- package/skills/conventional-commits/SKILL.md +10 -3
- package/skills/diagnose/SKILL.md +31 -0
- package/skills/dotnet-onion-api/SKILL.md +40 -3
- package/skills/e2e-verify/SKILL.md +88 -0
- package/skills/grill-with-docs/SKILL.md +19 -3
- package/skills/handoff/SKILL.md +11 -1
- package/skills/improve-codebase-architecture/SKILL.md +11 -1
- package/skills/migration-safety/SKILL.md +59 -0
- package/skills/nextjs-app-router/SKILL.md +36 -3
- package/skills/plan-and-build/SKILL.md +11 -1
- package/skills/pr-review/SKILL.md +25 -1
- package/skills/safe-refactor/SKILL.md +62 -0
- package/skills/security-review/SKILL.md +65 -0
- package/skills/ship-it/SKILL.md +15 -5
- package/skills/sql-review/SKILL.md +20 -0
- package/skills/task-executor/SKILL.md +15 -2
- package/skills/tauri-2-app/SKILL.md +28 -4
- package/skills/think-like-fable/SKILL.md +101 -0
- package/skills/upgrade-deps/SKILL.md +60 -0
- package/skills/write-a-skill/SKILL.md +29 -0
- package/skills/write-tests/SKILL.md +68 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: write-tests
|
|
3
|
+
description: Author tests that actually catch regressions — picks WHAT to test by risk (branch points, boundaries, error paths, money/auth/concurrency), proves every new test can fail (a test never seen red is decoration), mocks only boundaries you don't own, and pins untested legacy code with labeled characterization tests before anything else touches it. Use this skill whenever the user says "write tests", "add tests", "test this", "add coverage", "unit test this function", "increase coverage", "add a regression test", "characterization tests", "TDD this", or "/write-tests" — even if they don't explicitly say "test skill". Do not use for diagnosing a failing test (use diagnose) or reviewing existing tests as part of a diff (use code-review / pr-review).
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Write Tests
|
|
7
|
+
|
|
8
|
+
Author tests whose only job is to fail when the behavior breaks. Everything else — coverage numbers, green checkmarks, test count — is a proxy, and every proxy here can be gamed by accident. This skill makes the non-gameable thing the deliverable: each test is proven capable of failing, targets a behavior chosen by risk, and asserts what the caller can observe.
|
|
9
|
+
|
|
10
|
+
## When to use this skill
|
|
11
|
+
|
|
12
|
+
- The user says "write tests", "add tests", "test this", "add coverage", "unit test this", "add a regression test", "TDD this", "characterization tests", or "/write-tests".
|
|
13
|
+
- A feature just landed without tests, or plan-and-build / task-executor hands off a test-writing step.
|
|
14
|
+
- The user wants to change untested legacy code safely (pin first, then change — composes with `safe-refactor`).
|
|
15
|
+
|
|
16
|
+
Do **not** auto-trigger when the user is debugging a failing test (`diagnose`) or reviewing test quality in a diff (`code-review`, `pr-review`).
|
|
17
|
+
|
|
18
|
+
## Workflow
|
|
19
|
+
|
|
20
|
+
1. **Establish the baseline.** Detect the test runner (`package.json` scripts, `*.csproj`, `pytest.ini`, `go.mod`, `Cargo.toml`, `Makefile`) and run the existing suite **in non-interactive mode** — a `test` script that launches watch mode never exits and never yields a result; use the runner's single-run form (`CI=true`, `--run`, `--watchAll=false`, or the repo's `test:ci` script). Quote its summary line in your report. A result you didn't observe is `tests: not run`, never "passing". If the suite is already red, stop and surface it — new tests on a red suite are unverifiable.
|
|
21
|
+
2. **Read the whole unit under test**, not just the part the user pointed at. A claim about code you haven't opened is a hypothesis. Note every branch, early return, thrown/returned error, and boundary (empty, zero, max, null, duplicate, concurrent).
|
|
22
|
+
3. **Enumerate candidate behaviors and rank by risk.** Risk = likelihood of being wrong × cost of being wrong. Error paths, money, auth, deletion, retry/idempotency, and date/timezone logic outrank happy paths. Write the ranked list down before writing any test — it is the spec for step 5.
|
|
23
|
+
- ❌ One happy-path test per public method, top to bottom.
|
|
24
|
+
- ✅ Three tests on the refund-calculation branch and its rounding boundary, one on the happy path. The refund bug costs money; the happy path is exercised by every caller already.
|
|
25
|
+
4. **Check for existing coverage first.** Grep the test directory for the unit's name and read what's already asserted. Zero new tests is a valid outcome — if the ranked behaviors are covered, cite the existing test `file:line` and stop. Duplicating coverage is negative value: two tests break on every refactor instead of one.
|
|
26
|
+
5. **Write each test to a fixed shape.** Arrange-act-assert, one behavior per test, name = scenario + expected outcome (`refund_over_balance_is_rejected`, not `test_refund_2`). Assert observable behavior — return values, thrown errors, persisted state, emitted calls across a real boundary — never internal call order or private state.
|
|
27
|
+
6. **Prove each test can fail.** This is the step that separates a test from decoration, and it is not skippable:
|
|
28
|
+
- TDD path: write the test before the fix/feature, run it, quote the failure. Then make it pass.
|
|
29
|
+
- After-the-fact path: temporarily break the behavior under test (invert the condition, return the wrong value), run, confirm red, revert, confirm green. Quote both runs. **Mutation hygiene:** before reporting, run `git diff` on the production sources and confirm it contains none of your mutations — only the new test files. A leftover mutation is worse than no test; the green suite can't catch the one you made it agree with.
|
|
30
|
+
- A test that stays green against broken code is tautological. Fix its assertion or delete it — never ship it.
|
|
31
|
+
7. **Mock only boundaries you don't own** — network, clock, filesystem, database, message bus, external SDKs. Use the project's existing test-double convention (grep sibling tests for the fixture/mocking pattern and match it). Never mock the unit's own collaborators just to assert they were called: that welds the test to the implementation, and the test now fails on refactors and passes on bugs — the exact inversion of its job.
|
|
32
|
+
- ❌ `expect(userService.formatName).toHaveBeenCalledWith(user)` — asserts plumbing; survives `formatName` returning garbage.
|
|
33
|
+
- ✅ `expect(response.displayName).toBe("Rongo, Dennis")` — asserts the observable result; survives any internal restructure that keeps behavior.
|
|
34
|
+
8. **For untested legacy code: characterization tests first.** Capture what the code *does* (run it, record actual outputs for the ranked inputs), not what you believe it should do. If an output looks like a bug, pin it anyway with a comment: `// characterization: pins current (possibly wrong) behavior — see #issue`. Report the suspected bug separately; changing it is a behavior change, not a test.
|
|
35
|
+
9. **Final gate.** Run the full suite once more and quote the summary. Report: behaviors covered (with test names), behaviors deliberately not covered and why, and any suspected bugs found while reading. Rank the report — the two tests that matter, not fifteen equal bullets.
|
|
36
|
+
|
|
37
|
+
## Examples
|
|
38
|
+
|
|
39
|
+
### Example 1: "add tests for this service"
|
|
40
|
+
|
|
41
|
+
**User:** "Add tests for `InvoiceService.applyCredit`."
|
|
42
|
+
|
|
43
|
+
**Claude:** Runs the suite (quotes `47 passed`), reads the whole method plus the two private helpers it calls, ranks behaviors (credit > balance, negative credit, concurrent double-apply, happy path), finds the happy path already covered in `InvoiceServiceTests.cs:88`, writes the three missing tests, breaks the guard clause to prove each goes red, restores, quotes final green run.
|
|
44
|
+
|
|
45
|
+
### Example 2: pinning legacy code before a refactor
|
|
46
|
+
|
|
47
|
+
**User:** "I need to restructure this 400-line pricing function but there are no tests."
|
|
48
|
+
|
|
49
|
+
**Claude:** Enumerates its branches, runs the function against boundary inputs to record actual outputs, writes characterization tests pinning them (including one output that looks off, labeled and reported separately), proves they fail against a mutated copy, then hands off to `safe-refactor`.
|
|
50
|
+
|
|
51
|
+
## Anti-patterns
|
|
52
|
+
|
|
53
|
+
- ❌ Reporting "tests pass" without quoting an observed run — a result you didn't observe is "not run".
|
|
54
|
+
- ❌ Shipping a test you never saw red. Green-only tests are the largest source of fake coverage.
|
|
55
|
+
- ❌ Asserting a mock was called with the arguments you configured it with — the test proves the test.
|
|
56
|
+
- ❌ Testing private methods directly or reaching into internal state — test through the public surface; if a private method needs its own tests, that's a signal it wants to be its own module (note it, don't force it).
|
|
57
|
+
- ❌ Snapshot-testing large structures as a substitute for choosing an assertion — a 200-line snapshot fails on everything and tells the reader nothing.
|
|
58
|
+
- ❌ `sleep()`-based waits for async behavior — poll a condition or inject the clock; time-based tests are flaky by construction.
|
|
59
|
+
- ❌ Sharing mutable fixtures across tests so ordering matters — each test arranges its own world.
|
|
60
|
+
- ❌ Chasing a coverage percentage — coverage measures execution, not assertion. A line executed by a tautological test is worse than uncovered, because it looks protected.
|
|
61
|
+
- ❌ "Fixing" a legitimately-failing existing test by weakening its assertion to get to green — that's deleting a regression alarm; surface it instead.
|
|
62
|
+
- ✅ Ranked behavior list → match project conventions → observable assertions → every test proven red-capable → summary lines quoted.
|
|
63
|
+
|
|
64
|
+
## Notes
|
|
65
|
+
|
|
66
|
+
- Framework specifics (NUnit conventions for .NET APIs, RTL queries for React, etc.) come from the repo, not from memory — grep sibling tests and imitate the strongest existing example, matching its fixture, naming, and assertion style.
|
|
67
|
+
- When the unit is hard to test (needs six mocks, giant setup), say so in the report: test pain is design feedback. Offer `improve-codebase-architecture` rather than heroically mocking through it.
|
|
68
|
+
- Apply `think-like-fable` discipline throughout: effort follows risk (step 3), claims are re-derived not recognized (steps 1, 6), and the report leads with what matters.
|