Test Coverage Auditor: Turn Any Function Into a Complete pytest Suite Before Code Review

Why this prompt matters
Untested edge cases in payment-adjacent code — negative discounts, null inputs, rounding at boundary values — are a recurring source of production billing incidents precisely because they're the paths manual testing skips under deadline pressure. A discount function that silently allows a 150% discount, or rounds $19.995 down instead of up, doesn't fail loudly in a code review; it fails quietly in a refund queue three weeks later. Teams that ship this kind of function without edge-case tests routinely discover the bug only after a customer notices they were overcharged or undercharged, at which point it's a support ticket and a manual reconciliation instead of a five-minute fix caught in CI.
What we use it for
You're a backend developer at a mid-size e-commerce company. You just finished writing a discount-calculation function for the checkout flow, code review is in 20 minutes, and you haven't written a single test yet.
Prompt
Role: You are a senior QA engineer and test architect with expertise in [PROGRAMMING LANGUAGE] and [TESTING FRAMEWORK]. Context: I'm about to ship the following function/feature to production. Here is the code and its intended behavior: [PASTE CODE OR FUNCTION DESCRIPTION HERE]. This function will be called by [DESCRIBE CALLING CONTEXT, e.g., "a public API endpoint that receives untrusted user input" or "an internal batch job processing financial records"]. Task: Generate a comprehensive test suite for this function. Include: (1) happy-path unit tests covering the documented behavior, (2) edge cases (boundary values, empty/null inputs, extremely large inputs), (3) error scenarios and how the function should fail, (4) at least [NUMBER] integration test outlines describing how this function interacts with [DEPENDENT SYSTEM OR MODULE]. Constraints: Do not test implementation details that would break on refactor — test behavior, not internals. Flag any inputs where the expected behavior is ambiguous rather than guessing. Use [TESTING FRAMEWORK] syntax and conventions. Keep each test focused on one assertion or one logical scenario. Output Format: Organize as four sections with headers (Happy Path, Edge Cases, Error Scenarios, Integration Tests). For each test, give: a one-line description, the test code block, and a one-sentence note on what would break if this test failed. End with a short list of any ambiguous behaviors you flagged.
Result
Happy Path
Test: standard 20% discount applies correctly.def test_standard_discount():
assert apply_discount(100.0, 20.0) == 80.0
Breaks if: basic discount math regresses — the most visible failure a customer would notice immediately.
Edge Cases
Test: zero discount returns original price.def test_zero_discount():
assert apply_discount(50.0, 0.0) == 50.0
Breaks if: a no-op discount accidentally changes price via floating-point drift.
Test: 100% discount returns exactly zero.def test_full_discount():
assert apply_discount(75.0, 100.0) == 0.0
Breaks if: rounding leaves a residual charge like $0.01 on a 'free' item.
Test: price with sub-cent rounding boundary.def test_rounding_boundary():
assert apply_discount(19.99, 33.33) == 13.33
Breaks if: rounding mode rounds against the customer instead of to standard cents.
Error Scenarios
Test: negative discount percentage raises ValueError.def test_negative_discount_raises():
with pytest.raises(ValueError):
apply_discount(100.0, -10.0)
Breaks if: a negative discount silently increases the price instead of being rejected.
Test: discount over 100% raises ValueError.def test_over_100_percent_raises():
with pytest.raises(ValueError):
apply_discount(100.0, 150.0)
Breaks if: a checkout coupon bug applies a 150% discount and pays the customer to buy the item.
Integration Tests
1. Checkout API: verify the applied discount is persisted to the order record with the same rounding as the response body, so invoice totals match what the customer saw at checkout.
2. Coupon service: verify a discount capped by business rules (e.g. max $50 off) is enforced even when a stacked promo code would mathematically exceed it.
Ambiguous behaviors flagged: Should exactly 100.0% be allowed, or only up to 99.99%? Should the function round half-up or round-to-even (banker's rounding) at the cent boundary? Both need a product decision before the tests can be finalized.
Writing tests under deadline pressure almost always means writing the tests that are easiest to think of, not the ones that would actually catch a production bug. A function gets a happy-path test because that's the case the developer just finished coding against — the edge cases that would catch a negative discount, a null input, or a rounding error at a cent boundary get skipped, not because they're hard to write, but because under time pressure nobody thinks to ask what they'd even be.
Why the prompt demands four categories, not just "write tests"
Asking an AI to "write tests for this function" produces exactly the same blind spot a rushed developer has: mostly happy-path coverage with a token edge case or two. Forcing the output into four named categories — happy path, edge cases, error scenarios, and integration tests — makes each category a checklist item the model has to fill rather than an afterthought it can skip. Edge cases and error scenarios in particular are the categories most likely to be thin or missing entirely in an unstructured request, and they're also the categories most likely to contain the bug that eventually reaches production.
Why every test needs a "what breaks if this fails" note
A list of test names doesn't help a reviewer decide whether the suite is actually sufficient — it just proves that tests exist. Requiring a one-sentence note on what real-world failure each test would catch turns the output into something a reviewer can actually evaluate for coverage gaps: if the note for every edge-case test describes the same failure mode, that's a sign the tests are redundant rather than comprehensive. It also makes the tests useful documentation on their own, months later, when someone is deciding whether it's safe to delete or refactor one.
Why it refuses to guess at ambiguous behavior
Test generation prompts that always produce a confident, complete-looking suite are dangerous specifically because they look trustworthy. If the underlying function's behavior is genuinely undefined — should a 100% discount be legal, should rounding go up or down at a boundary — an AI that silently picks an assumption and writes a test asserting it has just encoded a guess as a regression test. The next developer who reads that test will treat it as documented, intended behavior. Forcing the model to flag ambiguity instead of resolving it protects against tests that quietly ossify an unreviewed guess into the codebase's source of truth.
Why it asks for integration outlines, not just more unit tests
Unit tests validate a function in isolation, but most production incidents happen at the seam between two correctly-functioning units — a rounding convention that's consistent within the discount function but doesn't match how the checkout API persists the same number. Asking for integration test outlines against the calling context, rather than just more unit tests, is what catches the class of bug that passes every unit test and still corrupts a customer-facing total.