These 12 unit test prompts help ChatGPT, Claude, Claude Code and Codex write tests that catch real bugs: test plans, edge cases, mocks, integration tests, property-based tests, test data and coverage gaps. Each prompt asks for a specific output, so you get tests you can review quickly.
Two basics, "write unit tests for this code" and "write a failing test for this bug", are in the coding prompts collection. The prompts below go further.
How do you use these prompts?
Copy a prompt and fill in the blanks in double braces, or keep the default after the colon. {{framework:Vitest}} means Vitest unless you change it.
Three habits make AI-written tests worth keeping:
- Show an existing test. The model copies your style, helpers and assertion library. The Claude Code common workflows page notes that Claude examines your existing test files to match the style, frameworks and assertion patterns already in use.
- Ask for behaviors, not lines. A list of behaviors to test is easier to check than a file of code.
- Run the tests. In an agent, ask it to run the new tests and show the output. A test that has never failed has not proven anything.
If you want an agent to work test-first by default, the TDD skill gives Claude Code a red-green loop with rules for good tests and mocks.
How do you write better unit tests?
1. Write a test plan before the tests
A plan is fast to review and catches missing cases before any test code exists.
Before writing any tests, list the behaviors of this
{{language:TypeScript}} function that need testing.
Give a table: behavior, example input, expected output or error, and
why it matters. Include normal cases, boundaries, invalid input and
error paths. Mark any behavior where the expected result is unclear
from the code, so I can decide.
{{code}}
2. Find edge cases with boundaries and classes
Bugs cluster at boundaries. This prompt makes the model look for them on purpose.
For the function below, split each input into equivalence classes
(groups of values that should behave the same) and list the boundary
values between them: zero, one, empty, maximum, just over the limit,
negative, null or undefined, and unusual text like emoji or very long
strings where relevant.
Then write {{framework:Vitest}} tests for the boundaries, one behavior per
test, as a table-driven test if the framework supports it.
{{code}}
3. Mock a dependency the right way
Over-mocking makes tests pass while the real code breaks. This prompt asks for the lightest replacement that works.
The code below depends on
{{dependency:an HTTP client and the current time}}.
I want to unit test it with {{framework:Vitest}}.
For each dependency, choose the lightest option: pass a real value, use a
simple fake, or mock it, and say why. Control time and randomness
explicitly. Assert on results and calls that matter to callers, not on
internal details. Show the tests.
{{code}}
4. Fix brittle tests
Tests that break on every refactor get ignored. This review finds why.
These tests fail every time we refactor, even when behavior doesn't
change. Review them.
{{tests}}
Code under test:
{{code}}
For each problem, name it (testing private details, too many mocks,
exact call order, snapshot of a large object, shared setup hiding what
matters, sleeps instead of waiting) and show the rewritten test that
checks the same behavior through the public interface.
How do you write integration tests?
5. Test an API endpoint against a real database
Integration tests prove the pieces fit. The setup and cleanup are where they usually go wrong.
Write integration tests for {{endpoint:POST /api/orders}} using
{{framework:Vitest}} and {{database:a real PostgreSQL test database}}.
Handler code:
{{code}}
How we start the app and connect in tests: {{setup}}
Cover: success, validation errors, auth failures, and a conflict or
duplicate case. Each test creates the data it needs and cleans up after,
so tests can run in any order. Fake only external services outside our
control, and say which ones you faked.
6. Test a client for a third-party API
For code that calls an external service you don't want to hit in every test run.
This code calls {{service:a payment provider's REST API}}:
{{code}}
Write tests that use recorded or hand-written HTTP responses, not the
live service. Cover: a normal response, an error status, a timeout, a
malformed body, and a retry if the code retries. Use responses shaped
like the provider's documented format, which I've pasted here:
{{sample_responses}}
How do you write property-based tests?
Property-based tests state a rule that holds for all inputs and let a library generate the inputs. Common libraries are fast-check for JavaScript and TypeScript and Hypothesis for Python.
7. Find properties and write the tests
The hard part is knowing which properties to state. This prompt suggests them.
Suggest properties for property-based testing of this function, then
write the tests with {{library:fast-check}}.
Kinds of properties to consider: round trip (decode of encode returns the
input), invariants (output is always sorted, total never changes),
idempotence (running twice equals running once), comparison with a
simple reference implementation, and "never throws" for valid input.
For each property, explain in one line why it should hold. Keep input
generators realistic for our domain: {{domain:order totals in cents}}.
{{code}}
8. Turn a shrunk failure into a regression test
When a property test finds a bug, keep the small example as a normal test so the bug stays fixed.
My property-based test found this failing case after shrinking:
{{failing_case}}
Property and function:
{{code}}
Explain why this input breaks the property. Write a plain example-based
test in {{framework:Vitest}} with this exact input, named after the bug.
Then suggest the fix, and say whether the property itself needs to
change because it was wrong rather than the code.
How do you create test data?
9. Write a test data builder
Builders give each test valid data by default, so tests only state the fields they care about.
Write a test data builder (or factory) in {{language:TypeScript}} for this
type:
{{type}}
Defaults must be valid and pass our validation rules: {{rules}}. Each
test should be able to override any field. Add named helpers for the
states we use most: {{states:a new user, a suspended user, an admin}}.
Avoid random values unless a seed controls them.
10. Generate edge-case-rich fixtures
Realistic data finds bugs that tidy test data hides.
Generate {{count:20}} test records for {{entity:customers}} as JSON matching
this schema:
{{schema}}
Include hard cases on purpose: names with accents, apostrophes and
non-Latin scripts, very long values, empty optional fields, time zones
far from UTC, dates near month and year boundaries, and duplicates that
differ only in case. List which record covers which case. Use obviously
fake emails and phone numbers.
How do you find gaps in test coverage?
Coverage tools show which lines ran. In Vitest, for example, the coverage guide shows running vitest run --coverage, with v8 as the default provider and istanbul as the other built-in option.
11. Read a coverage report for real gaps
Not every uncovered line matters. This prompt finds the ones that do.
Here is a coverage report for {{module:src/billing}} and the code.
Coverage report:
{{coverage}}
Code:
{{code}}
List the uncovered lines and branches that carry real behavior (business
rules, error handling, security checks), ranked by the damage a bug there
would do. Skip trivial code like simple getters. For the top five, write
the tests.
12. Ask which bugs your tests would miss
Covered lines can still hide bugs if no assertion checks the result. This is a manual version of mutation testing.
Here is a function and its tests. Act as a mutation tester.
Code:
{{code}}
Tests:
{{tests}}
Propose ten small bugs someone could introduce (flip a comparison,
remove a condition, return early, change a boundary, swap arguments).
For each one, say whether the current tests would fail. For every bug
the tests would miss, write the test that catches it.
Which test prompts should you turn into skills?
Prompts 1 and 12 are good candidates for a skill, so an agent plans tests and checks their strength every time without you pasting anything. Paste a prompt into the free SKILL.md generator to get a valid SKILL.md. To find the bug that a new test exposed, use the debugging prompts. To refactor safely once the tests are in place, see the refactoring prompts. For browser tests, the Playwright best practices skill helps an agent write and fix Playwright tests.
Kipt keeps prompts like these as Markdown in a private GitHub repo you own. Blanks like {{framework:Vitest}} stay as fill-in fields, tags and Cmd+K search find the right prompt, and the skills you keep there install into Claude Code or Codex with one command.