Verified against Cursor · 2026-07-21
Have Cursor's Agent mode write tests against the spec, not against whatever the code already does
An Agent-mode brief for generating tests against documented behavior rather than the implementation as found, with a forced tripwire requiring the model to prove each test would actually fail if the behavior broke, so a passing suite means something.
The prompt
Ready to copy — highlighted parts are example details you can swap.
Write tests for lib/pricing/applyDiscount.ts using Vitest with @testing-library conventions. Work in Agent mode: read the implementation yourself, but write tests against the expected behavior below — not against whatever the code currently happens to do if the two disagree. Flag any disagreement between the two instead of silently encoding the current behavior as correct just because it's what's there. BEHAVIOR THIS MODULE MUST GUARANTEE Applies a percentage discount, clamps the result at $0 minimum, and never discounts an already-free item further. EDGE CASES TO COVER EXPLICITLY Discount of exactly 100%, discount over 100%, negative price input, discount applied to a $0 item. EXISTING TEST CONVENTIONS IN THIS CODEBASE Test files live alongside source as *.test.ts, use describe/it blocks, and prefer toStrictEqual over toEqual for object comparisons. RULES - Every test must fail if the corresponding behavior breaks. Before finishing, pick one test per behavior and describe the specific code change that would make it fail, to prove it isn't vacuous. - Do not mock the function under test itself. - Do not write a test that only asserts a function was called — assert on its actual output or side effect, since a called-with assertion alone would still pass even if the real logic underneath were deleted. - If two of the edge cases above turn out to be handled by the exact same code path, say so instead of writing two tests that will always pass or fail together and calling that two units of coverage. - Follow the existing test conventions given above exactly — file naming, setup/teardown pattern, assertion style — rather than introducing a second convention alongside the first one in the same codebase. - If a behavior in the list is genuinely untestable without a change to the module itself (a hidden dependency, no seam to inject a fake), say so explicitly rather than writing a test that looks like it covers it but actually tests something adjacent.
Customize
Optional — swap in your own details for the highlighted parts above.
Why this works
Agent mode reads the implementation before writing tests, which creates a specific and well-documented failure mode: it's easy for a model to generate assertions that mirror the current implementation's exact behavior rather than the intended behavior, which lets a test suite pass at a high coverage percentage while encoding a live bug as "correct" permanently, since every future run confirms the bug is still there instead of catching it. Separating BEHAVIORS_TO_COVER from "go read the implementation" forces a comparison between intent and code instead of a transcription of one into the other, and explicitly asking it to flag disagreement gives it permission to say the code is wrong rather than assume the code is the spec by default, which is the model's natural resting assumption when no other source of truth is given. TEST_CONVENTIONS matters for a reason specific to agent-generated test suites rather than human-written ones: a model given no existing style to match will default to whatever pattern is most common in its own training distribution, which produces a second test-writing convention living alongside the codebase's actual one, and a codebase with two test styles is measurably harder for a human to scan for what's actually being asserted, since the reader has to first figure out which dialect a given file is written in before evaluating whether it's correct. The "describe what would make this test fail" step is a concrete tripwire against the single most common form of AI-generated test padding — an assertion that a mock was called, which adds a line of coverage-percentage without adding any actual regression protection, since it would still pass if the real logic were deleted entirely and replaced with a stub that just called through.
What you get back
describe('applyDiscount', () => { it('clamps at $0 minimum even with discount over 100%', () => { expect(applyDiscount(10, 150)).toBe(0) }) // Fails if the clamp is removed or changed to Math.max(-Infinity, ...) — // verified by temporarily removing the clamp and confirming it returns -5. it('never further discounts an already-free item', () => { expect(applyDiscount(0, 50)).toBe(0) }) }) Flag: edge cases "discount of exactly 100%" and "discount over 100%" both hit the same clamp branch in the current implementation — written as one parameterized test, not two, since they'd always pass or fail together.
Verified against
Cursor 2.2 · 2026-07-21
Changelog
- 2026-07-21 — Initial publish, verified against Cursor 2.2 Agent mode with Vitest.
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
