Memory

write-tests

Try it

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).

What it does

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 b…

The skill document

Write Tests

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.

When to use this skill

  • 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".
  • A feature just landed without tests, or task-executor hands off a test-writing step.
  • The user wants to change untested legacy code safely (pin first, then change — composes with safe-refactor).

Do not auto-trigger when the user is debugging a failing test (diagnose) or reviewing test quality in a diff (code-review).

Workflow

  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.
  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).
  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.
    • ❌ One happy-path test per public method, top to bottom.
    • ✅ 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.
  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.
  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.
  6. Prove each test can fail. This is the step that separates a test from decoration, and it is not skippable:
    • TDD path: write the test before the fix/feature, run it, quote the failure. Then make it pass.
    • 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.
    • A test that stays green against broken code is tautological. Fix its assertion or delete it — never ship it.
  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.
    • ❌ expect(userService.formatName).toHaveBeenCalledWith(user) — asserts plumbing; survives formatName returning garbage.
    • ✅ expect(response.displayName).toBe("Smith, Jane") — asserts the observable result; survives any internal restructure that keeps behavior.
  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.
  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.

Examples

Example 1: "add tests for this service"

User: "Add tests for InvoiceService.applyCredit."

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.

Example 2: pinning legacy code before a refactor

User: "I need to restructure this 400-line pricing function but there are no tests."

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.

Anti-patterns

  • ❌ Reporting "tests pass" without quoting an observed run — a result you didn't observe is "not run".
  • ❌ Shipping a test you never saw red. Green-only tests are the largest source of fake coverage.
  • ❌ Asserting a mock was called with the arguments you configured it with — the test proves the test.
  • ❌ 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).
  • ❌ Snapshot-testing large structures as a substitute for choosing an assertion — a 200-line snapshot fails on everything and tells the reader nothing.
  • ❌ sleep()-based waits for async behavior — poll a condition or inject the clock; time-based tests are flaky by construction.
  • ❌ Sharing mutable fixtures across tests so ordering matters — each test arranges its own world.
  • ❌ Chasing a coverage percentage — coverage measures execution, not assertion. A line executed by a tautological test is worse than uncovered, because it looks protected.
  • ❌ "Fixing" a legitimately-failing existing test by weakening its assertion to get to green — that's deleting a regression alarm; surface it instead.
  • ✅ Ranked behavior list → match project conventions → observable assertions → every test proven red-capable → summary lines quoted.

Notes

  • 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.
  • 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.
  • 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.

Related skills

Find why your productivity system keeps failing, then apply the smallest fix — capacity math, bottleneck routing, durable local notes.

by Iván855 installs69 stars

Stores durable facts in a categorized, plain-markdown vault on disk, alongside your agent's built-in memory.

by Iván559 installs18 stars

Generate and edit Draw.io, Mermaid, and Excalidraw diagrams from natural language using a structured JSON spec.

by nssa.io1.0k installs47 stars

Join a video meeting as an AI bot with voice, avatar, and screenshare across four operating modes.

by johnpatternai22 installs8 stars

Run Git operations — commits, branches, merges, rebases, conflict resolution, and recovery — with safety rules enforced.

by Iván535 installs31 stars

More from dennisrongo

Browse all skills

Surface architectural friction in a codebase and propose **deepening opportunities** — refactors that turn shallow modules into deep ones, informed by the project's `CONTEXT.md` glossary and `docs/adr/` decisions. Walks the codebase with an Explore sub-agent, applies the **deletion test** to suspected pass-through modules, presents a numbered list of candidates with files / problem / solution / benefits, and drops into a grilling loop once the user picks one — naming new concepts into `CONTEXT.md` inline and offering an ADR only when a rejection is load-bearing. Writes no production code. Use this skill whenever the user says "improve architecture", "improve the architecture", "architecture review", "find refactoring opportunities", "find deepening opportunities", "find shallow modules", "make this more testable", "this code is hard to navigate", or invokes `/improve-codebase-architecture` — even if they don't name the skill.

by dennisrongo3 installs

Write and run E2E tests for React Native / Expo apps using Maestro CLI — the open-source tool that drives the **real native app** on an Android emulator or iOS simulator, not a web build. Covers what browser-based e2e (Playwright, Expect, e2e-verify) cannot reach: native components, biometrics, secure storage, push notifications, platform-specific modules. Write YAML flows, run headed for authoring or headless for CI. Scripts currently automate the Android workflow end-to-end (Java + SDK detection, emulator boot, adb reverse); iOS simulator setup requires Xcode + `xcrun simctl` and is documented but not automated by the setup script. Use this skill whenever the user says "test my react native app", "e2e test the mobile app", "write maestro tests", "test the expo app", "automate emulator testing", or "/maestro-mobile-test" — even if they don't name the skill. Not for web apps (e2e-verify), unit/component tests (write-tests with RNTL + Jest), or API contract tests.

by dennisrongo2 installs

Verify a change end-to-end in a real browser, routed by one question — who needs this check to run again? Ephemeral checks run via Expect (millionco/expect) or browser-use (AI agent driving headless Chromium — references/browser-use.md) when installed, else Claude driving the browser directly; regression-critical flows (auth, money, signup, checkout, deletion) get durable Playwright tests under write-tests discipline. Evidence rule either way — an AI-walked flow yields "no issues found in the paths walked" with observations quoted, never "e2e passes". Safety gate: never production, never real user cookies. Use this skill whenever the user says "verify this in the browser", "test it end to end", "test my web app", "e2e test this", "write playwright tests", "run expect", "run browser-use", "smoke test the UI", or "/e2e-verify" — even if they don't name the skill. Not for native mobile (maestro-mobile-test), unit/integration authoring (write-tests), or debugging a failing e2e test (diagno

by dennisrongo1 installs

Pre-commit SQL code review for uncommitted database changes. Detects antipatterns that cause real production incidents — broken TRY/CATCH error handling, swallowed errors, retry patterns without loops, tables missing PK/indexes, type-mismatch truncation, dynamic-SQL injection, NOLOCK in write paths, UPDATE/DELETE without WHERE, hardcoded env values, cross-DB refs, and more (full catalog in the skill body). Reports BLOCKER/WARN/INFO findings with file:line citations and fixes. Never edits SQL. Use this skill whenever the user says "/sql-review", "review my SQL", "review the SQL diff", "lint the SQL", "check my SQL changes", "SQL pre-commit check", "audit my stored proc", or asks about SQL antipatterns in a diff — even if they don't name the skill. Distinct from code-review (general review) — this carries SQL-specific incident patterns.

by dennisrongo1 installs

Scaffold a new Tauri 2 desktop app (Rust backend + TypeScript/React frontend) using a thin-frontend / rich-Rust-backend architecture with modular commands, trait-based platform abstractions, encrypted secrets at rest, single-instance enforcement, a self-hosted updater, and a cross-platform CI matrix. Three modes: full project scaffold, add a Tauri command slice, add a Rust module slice. Use this skill whenever the user says "create a new Tauri app", "scaffold a Tauri 2 project", "new desktop app with Tauri", "Tauri + React project", "add a Tauri command end-to-end", "add a Rust module to my Tauri app", "my Tauri conventions", or "/tauri-2-app" — even if they don't name the skill. Full good-pattern catalog and pitfall list live in the skill body.

by dennisrongo1 installs

Turn a feature idea, conversation context, or rough notes into researched, detailed, dependency-ordered checkbox tasks appended to the project's roadmap/backlog file — exactly the format goal-runner consumes, so a fresh unattended session can execute them. Grounds every task in the actual codebase before writing it (grep/read or Explore scouts; think-like-fable rigor if installed), puts what + done-when on the checkbox line with verified files, acceptance criteria, and a verification command in plain sub-bullets, and labels assumptions. Appends to the existing ROADMAP.md/BACKLOG.md/TODO.md; when none exists it asks once and defaults to ROADMAP.md. Use this skill whenever the user says "add this to the backlog", "add it to the roadmap", "plan these tasks", "break this down into tasks", "capture this as roadmap tasks", "turn these notes into a task list", or "/backlog-planner" — even if they don't name the skill. Not for executing tasks (goal-runner, task-executor, autopilot) — this writ

by dennisrongo1 installs