šŸš€ LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
šŸŽ“ COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.
HTML MASTER CLASS /// LEARN TAGS /// BUILD STRUCTURE /// SEMANTIC WEB /// HTML MASTER CLASS /// LEARN TAGS ///

Generating Python Tests with AI

Using AI to generate genuinely useful tests — prompting for edge cases and failure modes specifically, and the review discipline that catches AI-generated tests verifying the wrong thing.

⚔ Total XP: 0|šŸ’» python XP: 0

Skill Matrix

UNLOCK NODES BY LEARNING NEW TAGS.

System Hub

Core logic.

Quick Quiz //

Why is a passing AI-generated test that asserts calculate_discount(100, 10) == 110.0 dangerous, specifically?


šŸš€ LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
šŸŽ“ COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.

AI-generated tests have a specific risk beyond ordinary AI-generated code: a test that looks reasonable but subtly verifies incorrect behavior is worse than no test at all, since it provides false confidence. This lesson covers prompting for genuinely useful test coverage and the review discipline that catches this specific risk.

1The Specific Danger: A Test That Verifies the Bug, Not the Fix

AI-generated tests carry a risk beyond ordinary AI-generated code's general need for review: a test generated by *running* the existing implementation and asserting on whatever output it happens to produce doesn't verify correctness at all — it verifies *consistency with current behavior*, which is a fundamentally different and much weaker guarantee. If calculate_discount(price, percent) has a genuine bug (adding the percent instead of subtracting it, an inversion this curriculum's Custom Exceptions and testing lessons would immediately flag as exactly the kind of error a real test should catch), a test asserting calculate_discount(100, 10) == 110.0 doesn't catch that bug — it *codifies* it, actively locking in the wrong behavior as the 'expected' result.

This is genuinely more dangerous than having no test at all for that function: a missing test is a known, visible gap — anyone looking at the test suite can see this function isn't covered. A test asserting the *wrong* expected value creates false confidence — the test suite reports 100% passing, the function *appears* verified, and a future developer who correctly fixes the actual bug (changing + to -) will find their correct fix now *fails* this incorrect test, creating exactly the kind of confusing, misleading signal that erodes trust in a test suite generally.

This is the single most important risk to understand about AI-generated tests specifically: the test 'passing' tells you nothing whatsoever about whether the assertion inside it is actually correct — only that it currently matches whatever the code happens to do, bug included. Every generated assertion requires independent verification against your own understanding of what the *correct* behavior should genuinely be, entirely separate from whether the test happens to pass against the current implementation.

āœ•
—
+
def calculate_discount(price, percent):
    return price * (1 + percent / 100)  # BUG: should be (1 - ...)

# An AI generating a test by RUNNING this buggy function and
# asserting on its output would produce:
def test_calculate_discount():
    assert calculate_discount(100, 10) == 110.0  # asserts the BUG's output!
# This test PASSES -- and permanently locks in the wrong behavior
localhost:3000
The False-Confidence Trap
A passing test only proves consistency, not correctness
An AI-generated assertion can codify an existing bug as 'expected'

2Independent Verification: The Non-Negotiable Review Step

Given this specific risk, the review discipline for AI-generated tests requires one additional, non-negotiable step beyond the general 'review AI-generated code' discipline from earlier lessons in this section: for every generated assertion, independently determine — using your own understanding of the requirement, not by trusting the test's own claimed expected value — what the *actually correct* result should be, and verify the assertion matches that independently-derived correct value, not merely that the test happens to pass.

For calculate_discount(100, 10), independent reasoning ('a 10% discount on $100 should reduce the price by $10, yielding $90') directly reveals that == 110.0 is wrong, regardless of whether the test 'passes' against the current, buggy implementation. This independent verification step is precisely what a test suite exists to provide in the first place — a check against an *external*, independently-determined standard of correctness, not a check that merely confirms internal self-consistency between a function and a test that was itself derived from that same function's current (possibly incorrect) output.

This connects directly to the Python Testing section's coverage of what a test's assertion should actually represent: a genuine, independently-reasoned specification of correct behavior, never merely 'whatever the code currently happens to produce.' AI-generated tests make this discipline more urgent to apply deliberately, precisely because the generation process (often, though not always, involving the assistant reasoning about or even executing the current implementation) can silently produce exactly this trap if the specific verification step isn't consciously, deliberately applied to every single generated assertion.

āœ•
—
+
# The test passing tells you NOTHING about correctness --
# only that the assertion matches whatever the code currently does

# Before accepting: independently verify
# calculate_discount(100, 10) SHOULD equal 90.0 (10% off $100)
# NOT 110.0 -- the generated test's assertion is WRONG, not the code
localhost:3000
Independent, Not Self-Referential Verification
Verify against YOUR reasoning about correctness
Not against whether the test happens to pass

3Prompting for Edge Cases: Where Bugs Actually Hide

Beyond the correctness-verification risk, there's a separate, complementary opportunity: a generic 'write a test for this function' request frequently produces only a single, obvious happy-path test case — exactly the scenario the original developer, writing the function in the first place, almost certainly already considered carefully and got right, making it the case *least* likely to ever actually reveal a bug.

Explicitly prompting for specific categories of edge cases — boundary values (0% discount, 100% discount), unexpected or invalid inputs (a negative percent — should this raise an exception, following the Custom Exceptions lesson's guidance, or is it silently accepted?), and extreme values (a percent over 100, which might produce a negative price) — directs generation toward exactly the categories of input disproportionately likely to reveal genuine bugs, mirroring precisely the boundary-condition testing philosophy the Parameterized Tests lesson established as a natural, high-value fit for exactly this kind of systematic coverage.

Combining this prompt-for-edge-cases technique with the independent-verification discipline from the previous section produces genuinely valuable AI-assisted test generation: broader, more deliberately-targeted coverage of the cases most likely to matter, with every single resulting assertion independently verified against actual correct behavior rather than merely accepted because the test happens to pass — the complete, professional discipline for making AI test generation a genuine asset rather than a source of dangerous false confidence.

āœ•
—
+
# Weak prompt: "write a test for calculate_discount"
# -> often produces ONE happy-path test

# Strong prompt: "write tests for calculate_discount covering:
# the happy path, a 0% discount, a 100% discount, a NEGATIVE
# percent (should this raise?), and a percent over 100"
# -> produces tests for the cases actually likely to reveal bugs
localhost:3000
Targeted, High-Value Coverage
Explicit edge case prompting
Targets boundary conditions and failure modes — where bugs actually tend to hide

4Step-by-Step Breakdown

A test suite full of tests that pass is only reassuring if those tests are actually verifying correct behavior — an AI-generated test asserting the WRONG expected value is a trap, not a safety net.

The DEFAULT risk: an AI-generated test can assert on whatever the CURRENT implementation happens to return -- even if that's actually WRONG.

Checkpoint: Why is a passing AI-generated test that asserts calculate_discount(100, 10) == 110.0 dangerous, specifically?

  • →If the underlying function has a bug (adding the percent instead of subtracting it), this test asserts on that BUGGY output, permanently locking in and 'protecting' the wrong behavior
  • →This is invalid pytest syntax and would fail to run at all

Verify EVERY assertion against your own independent understanding of correct behavior -- never accept an AI-generated assertion just because the test 'passes'.

Explicitly prompting for EDGE CASES and FAILURE MODES (not just the happy path) produces genuinely more valuable test coverage.

Checkpoint: Why does explicitly prompting for edge cases (0%, 100%, negative values) produce more valuable coverage than a generic "write a test" request?

  • →Edge cases and boundary conditions are disproportionately likely to reveal real bugs, compared to a single happy-path case that rarely fails
  • →It simply produces a larger raw NUMBER of tests, which is inherently better regardless of what they cover

Test generation verifies code behaves correctly; AI Code Reviews is next, using AI assistance to catch issues in code before it's merged at all.

Catch a Real Codified Bug. Finish test_matches_correct_formula(): verify the asserted value against the correct formula independently.

Level Up šŸš€

Advanced cheat sheets, SEO tricks, and interview prep for this topic.

Browser Support

ChromeSupported

Fully supported (via server-side Python execution).

FirefoxSupported

Fully supported (via server-side Python execution).

SafariSupported

Fully supported (via server-side Python execution).

EdgeSupported

Fully supported (via server-side Python execution).

Best Practices

Independently verify every AI-generated test assertion against your own understanding of correct behavior

A passing test only proves consistency with current behavior, not correctness -- an assertion generated from a buggy implementation's actual output can codify that bug as 'expected,' which is more dangerous than having no test at all.

Explicitly prompt for edge cases, boundary values, and failure modes, not just a generic "write a test" request

A generic request often produces only an obvious happy-path test, the case least likely to ever reveal a real bug -- explicit edge-case prompting targets the categories of input where bugs actually tend to hide.

Frequent Bugs

THE BUG

Accepting an AI-generated test's assertion because the test 'passes,' without independently verifying that the asserted expected value actually represents correct behavior, potentially codifying an existing bug as the test suite's expected result.

THE FIX

For every AI-generated test assertion, independently determine what the correct expected value should be (using your own reasoning, not the test's own claim), and verify the assertion matches that independently-derived correct value.

Real-World Examples

Catching a Codified Bug During AI-Generated Test Review

A developer generates tests for an existing function and, during review, independently verifies each assertion, catching a case where the generated test actually codified a pre-existing bug rather than correct behavior.

# AI-generated test (from running the current, buggy implementation):
def test_calculate_discount():
    assert calculate_discount(100, 10) == 110.0  # matches buggy output

# Independent verification during review:
# "A 10% discount on $100 should REDUCE the price to $90, not increase it to $110"
# -> This reveals the ASSERTION is wrong, which reveals the FUNCTION has a bug

# Corrected test, reflecting genuinely verified correct behavior:
def test_calculate_discount():
    assert calculate_discount(100, 10) == 90.0

Interview Prep

?Frequently Asked Questions

Pascual Vila

Pascual Vila

Frontend Instructor // Code Syllabus

Common Pitfalls & Errors

The Error //

Accepting an AI-generated test's assertion as correct simply because the test passes, without independently verifying the asserted value actually represents genuinely correct behavior, risking codification of an existing bug.

# Risky: accepted because it "passes" def test_calculate_discount(): assert calculate_discount(100, 10) == 110.0 # never independently verified # Correct: independently verified against actual requirement # "10% discount on $100 should yield $90, not $110" def test_calculate_discount(): assert calculate_discount(100, 10) == 90.0

The Solution //

Independently determine the correct expected value for every generated assertion using your own reasoning about the requirement, and verify the assertion matches that independently-derived correct value before accepting the test.

Lesson Glossary

[01]Codified bug

A test whose assertion matches an existing implementation's buggy output, effectively locking in and protecting incorrect behavior as "expected."

Code Preview
// Codified bug context

[02]Independent verification

Determining correct expected behavior through your own reasoning about the requirement, rather than trusting a generated assertion's claimed value.

Code Preview
// Independent verification context

[03]False confidence (testing)

A misleading sense of code correctness created by passing tests whose assertions do not actually verify genuinely correct behavior.

Code Preview
// False confidence (testing) context

[04]Edge case prompting

Explicitly requesting test coverage for boundary values and failure modes, rather than accepting a generic, often happy-path-only default.

Code Preview
// Edge case prompting context

Continue Learning