How to Prompt AI to Write a Test Plan

Ask AI for a test plan and you get the happy path. A six-group prompt scaffold that forces boundary, dependency failure, permission, concurrency and leftover-state cases, worked through a team invite feature, plus the review pass that catches confident nonsense.

Steve Jefferson
Steve Jefferson
Developer Advocate
28 August 20261 min read

Ask an AI for a test plan and you will get a competent list of things that work. Log in with valid credentials. Submit the form with correct data. Verify the record was created. It reads professional and it will not catch a single bug you actually have, because every item describes the path you already built and already tested by hand. The fix is not a better model, it is a prompt that names the categories of failure you want covered and refuses the happy path as a deliverable. Here is the scaffold, a worked example, and the review pass that catches what it still misses.

Why the default output is thin

A test plan is a prediction about how something breaks. Producing one requires a model of the system's edges: what state it holds, who is allowed to touch it, what happens when two people touch it at once, and what the code does when a dependency does not answer.

Given a feature description, a model has none of that. It has the description. So it enumerates the description, positively, in the order you wrote it. That is not laziness, it is the only thing available from the input you gave. Fix the input and the output changes shape entirely.

The scaffold

Paste this and fill the four bracketed sections. The structure matters more than the wording.

Write a test plan for this feature.

FEATURE
[What it does, in 3-5 sentences. Include what state it writes.]

SYSTEM CONTEXT
[Storage, auth model, external dependencies, background jobs.
 Who the user roles are and what each may do.]

CONSTRAINTS THAT MATTER
[Limits, quotas, timeouts, required fields, uniqueness rules,
 anything with a number attached.]

OUT OF SCOPE
[What is already covered elsewhere. Do not test these.]

Produce cases in exactly these six groups, and do not merge them:
1. Happy path (maximum 3 cases, these are the least useful)
2. Boundary and limit cases, using the numbers in CONSTRAINTS
3. Failure of each external dependency, one case per dependency
4. Permission cases: for each role, one thing they may do and
   one thing they must not
5. Concurrency and repeat: same action twice, two users at once,
   a retried request
6. State left behind: what is orphaned or inconsistent if the
   operation fails halfway

For every case give: preconditions, action, expected result, and
how a failure would be observed. If a group has no applicable
cases, write "none, because ..." and give the reason.

Three parts of that are doing the heavy lifting. Capping the happy path at three cases stops the model padding with the easy ones. Requiring an explicit "none, because" makes the gaps visible instead of silently absent. Asking how a failure would be observed forces each case to name a signal, which is what separates a test from a wish.

A worked example

Take a feature many people have built: a team invite. An admin enters an email address, the app sends an invitation link valid for seven days, and the recipient joins the workspace.

The unprompted plan gives you three cases about sending an invite and accepting it. The scaffold, with the constraint that links expire after seven days and each workspace allows ten seats, produces the cases that actually matter:

  • Boundary: accept the invitation on day six, and on day eight. Accept a link at the exact expiry moment.

  • Boundary: invite the eleventh member on a ten-seat plan. Then invite the eleventh after a member has been removed.

  • Dependency failure: the email provider returns an error after the invitation row is written. Is there an invite in the database for a mail nobody received?

  • Permission: a non-admin member calls the invite endpoint directly rather than through the button. A removed admin uses a link they still have open in a tab.

  • Concurrency: two admins invite the same address within the same second. One recipient clicks the same accept link twice.

  • State left behind: the workspace is deleted while an invitation is outstanding. The recipient clicks the link.

That last one is the bug. It is the case nobody writes by hand and no happy-path plan contains, and it is the sort of thing that produces a support ticket six months later from someone staring at an error page.

Give it the real constraints or expect generic output

The single largest difference in output quality comes from the CONSTRAINTS block. Vague inputs produce vague cases.

"There is a limit on invitations" gets you "test that the limit is enforced". "Ten seats per workspace, invitations expire after seven days, one pending invitation per email address, and removing a member frees the seat immediately" gets you the eleventh-member-after-removal case, which is a real interaction between two rules you wrote separately and never tested together.

The corollary: anything you cannot state as a number or a rule, the model cannot test against. If writing the CONSTRAINTS block is hard, you have found an ambiguity in the feature, which is worth more than the test plan.

Review the plan before you trust it

The scaffold produces good coverage and confident nonsense in the same document. Four things to check every time.

  1. Delete cases that test the framework rather than your code. "Verify the database rejects a null in a not-null column" is not your test.

  2. Check every number against the source. Models will assert a thirty day expiry because that is the common default, not because you said so. Any number that did not come from your CONSTRAINTS block is a guess.

  3. Look for cases that cannot actually be observed. If the expected result is "the system handles it gracefully", that is not a result, and the case needs a concrete signal or it needs cutting.

  4. Read the "none, because" entries hardest. That is where the model tells you what it decided not to cover, and it is frequently wrong about why.

The same verification discipline applies whenever a model produces something that looks like specification, which is why stopping AI from making up citations and this problem are the same problem wearing different clothes.

From plan to actual tests

A test plan is not test code and converting it in one step produces shallow tests. Two useful intermediate moves.

Ask for the test data first. A plan that says "invite the eleventh member" needs a workspace at ten seats, and generating that fixture is its own task. Prompting for realistic test data covers doing that without ending up with a hundred records named Test User.

Then convert one group at a time, not the whole plan. Group 3 and group 6 tests need dependency mocking and cleanup verification that group 1 tests do not, and asking for all of it at once produces uniform, mediocre coverage. Using AI to write tests goes into the conversion step properly.

If you are wondering where this leaves a QA function, the honest answer is that the plan is the cheap part and the judgement about what matters is not. We wrote about that split in can AI replace your QA team.

FAQ

Why does AI default to happy path test cases?

Because a feature description contains only the intended behaviour. Without explicit system context, constraints and failure categories, enumerating the description positively is the only thing the input supports.

How much context does it actually need?

Enough to name edges. Storage, auth roles, external dependencies, and every rule with a number in it. That is usually ten to fifteen lines and it is the difference between generic cases and specific ones.

Should I ask for test code directly instead?

Not in one step. Generating code straight from a feature description skips the coverage question entirely and you end up with well-written tests for the wrong things. Plan first, review, then convert group by group.

What do I do with the "none, because" entries?

Read them closely. They are the model's stated reason for skipping a whole category, and a wrong reason there hides more risk than a wrong individual case.

Does this work for manual test plans too?

Yes. Nothing in the scaffold assumes automation. The six groups and the requirement to state how a failure is observed apply equally to a plan a person will execute by hand.

How did this land?

About the author

Steve Jefferson
Steve Jefferson

Developer Advocate

Steve builds something with Swarmz every week and writes up what worked, what broke, and what he'd do differently. Tutorials and hands-on guides are his lane.

Share

Get the next post in your inbox

One email a month. Product updates, engineering posts, and the best of Built with Swarmz.

I agree to receive emails about AI building tips and Swarmz product news. Unsubscribe any time.