GitHub Copilot

Verified against GitHub Copilot Chat · 2026-08-11

Push Copilot's /tests beyond the happy path with edge cases it won't reach for on its own

A prompt that layers named edge cases and mocking boundaries on top of Copilot Chat's /tests generation, so the resulting suite exercises the failure paths you actually care about instead of one clean happy-path test per function.

GitHub Copilot Chat5 fillable variables

The prompt

Ready to copy — highlighted parts are example details you can swap.

Generate unit tests for the function below using Vitest, with describe/it blocks and the existing project's custom `renderCart()` test helper, matching the conventions of the existing test file so this reads like it was written by the same person, not a separate generated block bolted on afterward.

FUNCTION UNDER TEST
applyDiscountCode(cart, code) in checkout/discounts.ts

EXISTING TEST FILE FOR STYLE REFERENCE
checkout/discounts.test.ts

EDGE CASES THAT MUST BE COVERED
Discount code applied twice in one session, code that's valid but the cart total is below the minimum spend, and a code that expired exactly at the current timestamp (boundary, not just past-expiry).

WHAT TO MOCK VS. WHAT TO LEAVE REAL
Mock the external pricing API call, but let the actual discount-calculation math run for real — don't mock the function under test's own internal logic.

WHAT NOT TO DO
Do not stop at one happy-path test and call the suite done — a single passing-input test is the case Copilot generates by default with no further instruction, and it is also the least useful one, since it's the case most likely to have already been checked manually before the code shipped. Do not mock something the mocking boundary above says should stay real, even if mocking it would make the test simpler to write — a test that mocks around the exact thing it should be verifying gives false confidence, not real coverage. Do not invent an edge case that isn't listed above and isn't a case any reasonable reading of the function would surface (like null input or an empty array) — pad the suite with cases that matter, not with cases that exist only to inflate the count. Do not rename or restructure existing tests in the reference file; only add new ones in the same style.

For each edge case listed above, write one test that isolates it — don't fold two edge cases into a single test where a failure would be ambiguous about which condition actually broke. If a listed edge case turns out to be already covered by an existing test in the reference file, say so explicitly instead of duplicating it.

OUTPUT FORMAT
1. New test cases, in the same file and style as the existing reference file.
2. A one-line note for any listed edge case that was already covered and therefore skipped.
3. A short list of any edge case you'd recommend adding beyond what was listed, with a one-sentence reason each — as suggestions only, not added to the file unless I ask.

Customize

Optional — swap in your own details for the highlighted parts above.

Why this works

Copilot's /tests command, run with no further instruction, is trained to produce output that looks complete at a glance — typically one test per function covering the input the function was clearly designed for — because that's the shape of test that appears most often in the training distribution of committed code, not because it's judged the function's actual risk surface. Naming edge cases explicitly overrides that default by giving the model a concrete, finite list to check off rather than an open-ended 'be thorough' instruction it has no way to bound; an unbounded thoroughness request tends to produce either too few cases (stopping once it feels sufficient) or padding with trivial variations that don't map to a real failure mode. The mocking boundary is the single highest-leverage line in this prompt because Copilot Chat, left to its own judgment, will often mock whatever makes a test easiest to write rather than whatever preserves the test's actual purpose — it has no inherent sense of which dependency is incidental infrastructure (an external API) versus the exact logic the test exists to verify, so an unstated boundary produces tests that pass reliably while verifying almost nothing. Requiring one isolated test per edge case rather than combined multi-condition tests matters for diagnosability: a test asserting two conditions at once tells you it failed, not which condition broke, which defeats the point of writing edge-case tests in the first place — the value of an edge-case suite is in the specificity of its failure signal, not just its pass/fail count. Matching the existing file's style also avoids a subtler cost: a generated block that looks structurally different from hand-written tests around it gets treated by future readers as less trustworthy scaffolding, even when its assertions are correct.

What you get back

it('rejects a discount code applied twice in the same session', () => { ... expect(applyDiscountCode(cartWithCodeAlreadyApplied, 'SAVE10')).toThrow('Code already applied') }); it('rejects a valid code when cart total is below minimum spend', () => { ... }); it('treats a code expiring at the exact current timestamp as expired, not valid', () => { ... }). Note: the 'invalid code format' edge case is already covered by the existing `rejects malformed codes` test in discounts.test.ts, so it was skipped here.

Verified against

GitHub Copilot Chat 2026.08 · 2026-08-11

Changelog

  • 2026-08-11 Initial publish, verified against GitHub Copilot Chat 2026.08.

Need this built into your business?

If a prompt isn't enough — custom software, built and maintained for you — that's Scult's day job.

EXPLORE CUSTOM SOFTWARE
Write a .github/copilot-instructions.md file Copilot actually followsA repository-wide custom-instructions file that Copilot loads automatically into every Chat request, code-review pass, coding-agent session, and commit or PR-description generation in this repo, written so each rule holds up standing alone instead of only in the context it was written in.GitHub Copilot Chat (VS Code)GitHub Copilot code review2026-07-20Scope Copilot's instructions to one directory with an applyTo instructions fileA path-scoped .github/instructions/*.instructions.md template using the applyTo frontmatter glob, so a directory-specific rule — a different test framework, a stricter API contract, a legacy pattern that must not spread — applies only where it is actually true instead of polluting the repo-wide instructions file.GitHub Copilot Chat (VS Code)GitHub Copilot coding agent2026-07-21Define a custom Copilot Chat mode instead of re-explaining your workflow every sessionA .github/chatmodes/*.chatmode.md definition — scoped tools, a fixed model, and a narrow system prompt — that turns a repeated review-and-plan style of conversation into a mode you switch into once, instead of a persona you re-describe in the first message every time.GitHub Copilot Chat (VS Code)2026-07-22Turn a prompt you keep retyping into a Copilot prompt file instead of pasting it againA .github/prompts/*.prompt.md reusable prompt file with input placeholders, invoked as a slash command from the Chat input box, so a well-tuned multi-paragraph prompt becomes one command instead of a paste you have to keep re-finding.GitHub Copilot Chat (VS Code)2026-07-22
All GitHub Copilot prompts

Check your AI visibility

One URL in, a 0–100 score and the exact fixes out.

RUN THE CHECK

Browse all the tools

15 tools across six categories
13 of them never send your data anywhere

Free · No signup · No trial clock

SEE THE DIRECTORY