Chapter 10 of 18

Tests

What a test proves and what it does not, from a first unit test to mutation testing and hidden scenarios.

A green test run feels like proof. What it really says is narrower: the checks somebody wrote all passed. It does not say those checks could have failed, or that they look at anything you care about, or that the person who wrote them understood the job.

That gap was always there. Agents make it wider, because now one mind with one misunderstanding writes the code and also writes the marking scheme. StrongDM's AI team hit this early, and described it plainly: "return true is a great way to pass narrowly written tests". An agent under pressure to go green has several easy ways to get there, and most of them look fine in a summary.

So this chapter goes in two halves. The first gets you from a single assertion to the working vocabulary of tests: what kinds there are and what each one can see. The second is the part that matters more now: how to test the tests, using coverage and why it fools you, mutation testing, and generated inputs. Then the climb past tests altogether, from examples to rules, to every state, to proof, with what each step can and can't show. It ends with scenarios the agent is never allowed to read, and the argument over where a limited budget should go.

Test

Also called Automated test

A small program that runs your code with a known input and checks the answer. If the answer is wrong it fails, loudly, without a person watching.

An agent can't see whether its work is right, but it can read a failure. A test is the cheapest way to turn "does this work?" into something it can act on in a loop.

Say it to your agent

“Write a test for total() in src/cart.test.ts that passes [200, 350] and expects 550, and one that passes [] and expects 0. Run bun test and show me the output.”

A test is really two things: some code that runs, and one line that says what should have happened. Only the second can fail for the reason you care about.

Assertion

The line in a test that compares what happened with what should have happened, such as expect(total).toBe(550). Without one, a test only proves the code did not crash.

Agents reach for weak assertions, like "the result exists", because they pass quickly. The strength of the suite lives almost entirely in these lines, so these are the lines to read.

Say it to your agent

“These tests only check that the result is defined. Change each assertion to the exact expected value, such as expect(discount(200, 10)).toBe(180), and add a case at percent 0 and percent 100.”

Test runner

The program that finds your tests, runs them, prints what failed, and exits with a code saying whether everything passed. Examples are bun test, Vitest, pytest and Playwright Test.

The exit code is what lets a hook or a pipeline stop an agent. A runner that prints a failure but exits 0 lets the agent carry on as if nothing happened.

Say it to your agent

“Add a "test" script to package.json that runs bun test. Show me that it exits 1 when I break a test on purpose, and 0 again when I put it back.”

Tests differ mostly in how much of the system they switch on. More real parts means more truth, and also more time and more ways to fail for no good reason.

Unit test

A test of one small piece of code on its own, usually a function. It runs in milliseconds and points straight at what broke.

Fast tests are the ones an agent can run on every attempt. They also suit agents badly in one way: they can pass while the pieces fail to fit together, and they are the easiest kind to write without checking anything.

Say it to your agent

“Add unit tests for parsePrice in src/price.ts: normal input, an empty string, a negative number and "1,000.50". No network, no database, and the whole file should run in under 100 ms.”

Fixture

The known starting state a test sets up before it runs: a sample user, a few rows in a table, a file on disk. Good ones are created fresh for each test.

Agents love to share a fixture between tests because it saves lines. That is how you get a suite that passes in one order and fails in another.

Say it to your agent

“These tests share one users array and they mutate it. Move it into a makeUsers() function, and call that in each test, so that no test can see another test's changes.”

Test double

Also called Stand-in, Fake, Stub, Spy, Dummy

Anything that replaces a real part of your system during a test, like a stunt double. It lets you test without charging a real card or waiting on a real server.

Every double is a claim about how the real thing behaves. Nothing checks that claim unless you make something check it, and an agent writes the claim from what it assumes.

Say it to your agent

“Do not call the real Stripe API in tests. Write a FakeGateway in tests/fakes/ that keeps charges in an array, and pass it in. Use the fake for the outside service only, and keep our own code real.”

One kind of double deserves a warning, because it is the easiest way for an agent to write a test that tests only itself.

Mock

A test double that records how it was called, so the test can check the calls. In casual use, people say mock for any stand-in.

If the agent mocks too much, the test exercises the mocks and not your code. It stays green whatever you break, and it fails when you tidy up the internals.

Say it to your agent

“This test mocks priceCart and then only checks that it was called. Keep our code real and mock only the payment gateway. Assert on the amount it received. Then break priceCart on purpose and show me the test failing.”

Integration test

A test where several real pieces work together: your code against a real database, or two of your services talking to each other. It is slower, and it finds the bugs that live in the joins.

Agents write confident code against an interface they have guessed at. A real query against a real database settles the guess at once, which no unit test can do.

Say it to your agent

“Add an integration test for createOrder that uses a real in-memory SQLite database, runs the migrations, and checks the rows afterwards. Don't mock the database.”

Contract test

A check that a real outside service still behaves the way your test doubles say it does. If the provider renames a field, this fails, even while everything else stays green.

A double only remembers how the service worked on the day it was written. An agent trusts it completely, and will happily build on a shape the real service stopped sending months ago.

Say it to your agent

“Add tests/contract/payments.contract.test.ts. It calls the provider's sandbox and checks that the response has the same fields and types as our FakeGateway returns. Run it nightly, not on every commit.”

End-to-end test

Also called E2E test

A test that drives the whole system the way a user would: a real browser, clicking real buttons, against the real app and its database.

An agent can only claim a screen works until something looks at it. An end-to-end test can be its eyes. It is also the slowest and flakiest kind, so keep a few that matter and not hundreds.

Say it to your agent

“Write one Playwright test for the checkout: sign in, add an item, pay with the test card, and check the confirmation page shows the order number. Wait on what the page shows, and use no fixed sleeps.”

Acceptance test

Also called Gherkin

A test written from what the customer asked for and not from how the code works. Often written in Given, When, Then sentences that a person can read and a tool can run.

It is written before the code exists and from the request, so it is harder for the agent to fit it to whatever it happened to build. A person can also read it and say "that isn't what I meant" before any code gets written.

Say it to your agent

“Before writing any code, write features/refund.feature in Gherkin: Given an order paid yesterday, When the customer asks for a refund, Then the status is refunded and the money is returned once. Stop and let me approve it.”

Smoke test

A very quick check that the thing runs at all: it starts, the main page loads, the health endpoint answers. It says nothing about whether it is right, only whether it is on fire.

Agents can write a thousand lines and never start the program. A ten-second smoke test catches the embarrassing failure, and it is a sound first gate because it costs almost nothing.

Say it to your agent

“Add scripts/smoke.sh: start the server, wait up to 10 seconds for GET /health to return 200, load / and check the status is 200, then shut it down. Exit 1 if any of that fails. Run it before the full suite.”

Test pyramid

A rule of thumb for the mix: many fast unit tests at the bottom, fewer integration tests in the middle, and very few slow end-to-end tests on top.

An agent runs your tests over and over in a loop, so slow tests cost you on every attempt. It is cheap for an agent to write a slow test now. Waiting for it, and working out why it flaked, is still expensive.

Say it to your agent

“The whole suite takes 9 minutes because everything goes through the browser. Keep the 5 most important journeys as Playwright tests, and rewrite the others as unit or integration tests. Target under 60 seconds in total.”

Now for the first way a test lies: it changes its mind.

Flaky test

A test that sometimes passes and sometimes fails on the same code. Usually the cause is timing, shared state or something outside the test, such as the network or the clock.

A flaky test teaches everyone to ignore red. An agent is worse: it may "fix" code that was fine, or retry until it gets a green run and report success. Retries hide the fault and do not remove it.

Say it to your agent

“cart.test.ts fails about one run in five. Run it with bun test --rerun-each 50 and with --randomize to find out whether it is timing or order. Replace the fixed sleep by awaiting the real promise. Don't add retries.”

Some tests are written to record a mistake, so that it can't come back.

Regression test

A test written after a bug, which fails on the old code and passes on the fix. A regression is when something that used to work stops working.

An agent has no memory of last month's bug, and may reintroduce it while tidying up. The test remembers. It only counts if you have seen it fail on the broken version.

Say it to your agent

“Before you fix this: write a test that reproduces it, run it, and paste the failure. Commit that. Then fix it, run it again, and paste the pass. I want both outputs in the pull request.”

Others record what the code does now, whether or not that is right.

Snapshot test

A test that saves the output once to a file, then fails whenever later output differs. It tells you something changed. It can't tell you whether the change is good.

When a snapshot fails, the easy way out is one flag that rewrites the file, and an agent will take it. Your bug is now the expected answer, and the test will defend it.

Say it to your agent

“A snapshot failed. Do not run --update-snapshots yet. Show me the diff of the snapshot file, and say in one sentence why each changed line is intended. I will decide.”

Characterisation test

Also called Golden master test

A test that records what old code does today, bugs included, so you can change it safely. You are writing down the behaviour before you touch it, without claiming that it is right.

This is how you let an agent refactor code nobody understands. Pin the behaviour first, then any change it makes by accident shows up. Tell it the bugs stay until you decide otherwise.

Say it to your agent

“Before refactoring src/legacy/invoice.ts, run it on these 30 real inputs, and save each output as a test in invoice.characterisation.test.ts. They must all pass unchanged after the refactor. If you find a bug, report it and don't fix it.”

When should the test get written? People have argued over this for twenty years, and the evidence has not settled it.

Test-driven development

Also called TDD

Writing the test before the code that makes it pass, in very small steps. The test fails first, because the code does not exist yet, and that failure is the point.

With agents the argument changes. A test written first can't be fitted to the code, and watching it fail shows it can fail at all. Those are strong reasons whatever the studies say about people. We found no good trials on agents.

Say it to your agent

“Use red/green TDD for this. Write one test, run it and show me it failing. Then write the least code that passes. One test at a time, and do not change a test to get it to pass.”

Red, green, refactor

Also called Red/green TDD

The TDD cycle in three steps. Red: write a test and watch it fail. Green: write just enough code to pass. Refactor: tidy up while the tests stay green.

For an agent, red is the step that matters. A test that passes before the code exists is a test that can't fail, and an agent left alone will skip straight past that without noticing.

Say it to your agent

“Show me the red: paste the failing test output before you write any code. If a new test passes on the first run, stop and tell me, because it isn't testing what we think it is.”

That covers how tests get written. Now the harder question: when a test passes, what does that actually prove? Start with where the right answer came from.

Test oracle

Whatever tells you what the right answer is. It may be a number you worked out by hand, a spec, an old system, or a rule that must always hold.

If an agent writes the code, runs it, and pastes the output in as the expected value, the oracle is the code itself. The test will pass for ever, and it proves nothing. Always ask where the expected value came from.

Say it to your agent

“Where did 1847.52 in this test come from? If you got it by running the code, delete it. Work it out from the rule in docs/pricing.md, show the sum in a comment, and use that.”

Coverage

Also called Line coverage, Code coverage

The share of your code that ran during the tests. It says what ran. It says nothing about whether anything checked the result.

Low coverage tells you something real: that code has never been run by a test. High coverage tells you much less, and it is trivially easy for an agent to hit any number you give it.

Say it to your agent

“Run bun test --coverage and list the lines nothing runs. Don't add tests just to raise the number. For each uncovered line, say what would go wrong if it were broken, then write an assertion that would catch it.”

Tautological test

Also called Assertion-free test

A test that can't fail, because it compares the code with itself, checks nothing, or only checks something that is always true.

These are what an agent produces when asked to "add tests". They look like work, they raise coverage, and the summary says "47 tests pass". One quick check finds the worst of them: make every function return nothing and see what still passes.

Say it to your agent

“Stub every exported function in src/price.ts so it returns undefined, and run the tests. List every test that still passes, then rewrite or delete them. Expected values must be literal numbers and not computed.”

Before reaching for a better number, it is worth knowing what happens to numbers.

Goodhart's law

When a measure becomes a target, it stops being a good measure. Point anyone at a number and they will move the number, whether or not the thing it stood for moves too.

An agent optimises what the check reads, faster and more literally than a person. Any number you put in a gate can go up for the wrong reason, so keep at least one check it can't see and can't optimise for.

Say it to your agent

“I do not care about the coverage number. Tell me which behaviours are still unchecked. If you delete code to improve a score, list each deletion and say why that code could never run.”

So here is how you test the tests. Break the code on purpose, in small ways, and see whether anybody notices.

Mutation testing

A tool makes one small deliberate bug in your code, such as changing a < to <=, and runs your tests. If they fail, that bug was caught. If they still pass, your tests have a blind spot exactly there.

This is the check that makes it hard for an agent to mark its own homework, because it doesn't trust the green. And a surviving mutant is a perfect instruction: it names a line and a change no test noticed.

Say it to your agent

“Run bunx stryker run on src/price.ts. For every survivor, either add a test that kills it, or explain why it can't be killed. Don't delete code to raise the score without saying so. Show me the before and after.”

Mutation score

The share of deliberate bugs your tests caught: killed divided by total. 18 of 30 is 60%. It measures how strong the tests are, not how right the code is.

It gives an agent a number to climb and a list of what to fix. It also can't see anything nobody asked for: tests can catch every mutant in code that solves the wrong problem.

Say it to your agent

“Report the mutation score per file, as killed / total, with the survivors listed. Treat anything under 70% on a changed file as blocking, and don't treat any score as proof that the behaviour is what I asked for.”

Equivalent mutant

A mutant that changes the code but not what it does, so no test could ever catch it. It survives, and that says nothing bad about your tests.

So 100% is not always possible, and "kill every survivor" needs judgement. Push an agent too hard and it will write strange tests, or bend the code, to chase mutants that are not real bugs.

Say it to your agent

“For this survivor, compare the mutant with the original over a wide range of inputs. If you find an input where they differ, write the test for it. If you can't, say that it is equivalent and show me what you tried.”

Everything so far relies on somebody choosing the inputs, and an agent chooses the inputs it already handled. So stop choosing them.

Property-based testing

Also called Generative testing

Instead of a few examples, you state a rule that must always hold, such as "the shares always add up to the bill". The tool invents hundreds of inputs, and when one fails it cuts it down to the smallest input that still fails.

It is much harder to fit code to a rule than to an example. Rules also answer the oracle problem: you may not know the right split of 7312 between 6, but you know it has to add up. For an agent, the shrunk failure makes a very clear bug report.

Say it to your agent

“Add fast-check to splitBill's tests with bun add -d fast-check. Assert for all totals and weights: shares sum to the total, every share is a whole number, and there is one share per person. Paste the shrunk counterexample if it fails.”

Fuzzing

Also called Fuzz testing

Throwing huge numbers of random or damaged inputs at a program to see if it crashes or hangs. You do not need to know the right answer, only that it should survive.

Agents tend to write the happy path and test the happy path. A fuzzer has no idea what the happy path is. That makes it especially good for anything that parses input from outside, which is often where the security bugs are.

Say it to your agent

“Write a fuzz test for parseCookie: generate 100,000 strings, some random and some damaged copies of "a=1; b=2", and fail if it throws anything other than our own ParseError. Add every crash you find as a regression test.”

So far every check is one somebody wrote in advance. The oldest check of all needs no foresight: start the thing and look at it.

Empirical verification

Also called Prove it works, Run it and look

Checking a claim by running the real program on the surface a user touches and looking at what happens: open the page, send the request, read the row in the database. What you saw counts, and what the agent says it saw does not.

An agent's "it should work now" is a prediction, and "it compiles" is a proxy. A real run is the check that catches what nobody wrote a test for, such as a page that renders blank. It costs tokens and time, and it proves only the paths you drove.

Say it to your agent

“Don't tell me it works. Start the app with bun run dev, drive /checkout in Playwright with the test card, and paste the order number, a screenshot, and the row from SELECT * FROM orders ORDER BY id DESC LIMIT 1. Save those steps as scripts/verify-checkout.ts so I can re-run them.”

A real run shows you one path. To ask about all of them, you first need to say what would count as wrong on any of them.

Invariant

Something that must always be true, at every moment, whatever happens: a balance never goes below zero, a refunded order never ships, the shares always add up to the bill. It is a plain sentence first and code second.

You can say an invariant without reading the code, which makes it the part of the job you can do and an agent can't guess. It is also what every check from here up needs: a tool can try every order of events only if something says which outcomes are wrong.

Say it to your agent

“Write three invariants for refunds in docs/invariants.md, in plain English first: total refunded never exceeds the amount paid, a refunded order never moves to shipped, and every refund row points at a real payment. Add a fast-check property for each, and show each one failing on a copy you have broken on purpose.”

Random inputs are a poor way to find a bug that depends on the order things happen in, because that order may turn up once in a thousand runs. So write down a small model of the system, and visit every state it can reach.

Model checking

Also called TLC, Explicit-state checking

A tool walks every state a small model of your system can reach, in every order the steps could happen, and checks an invariant in each. If one breaks, it hands you the shortest sequence of steps that gets there. The model is a short description of the design, not your code.

Agents write the happy order and test the happy order, and a race only shows on some other order. The checker doesn't need to be lucky. But it checks the model the agent wrote, so a step the model leaves out can't fail. Replay every counterexample on the real code, and make sure a broken model fails.

Say it to your agent

“Write a TLA+ model in specs/withdraw.tla: two requests, each with a separate check step and debit step, from a balance of 100. Add INVARIANT BalanceNeverNegative, run TLC and paste the shortest trace. Then replay that trace against the real code as a test, one step per action. If the bug doesn't appear, assume the model is wrong.”

A model checker still stops at a bound. The last step up is a proof: an argument a machine checks, covering every input, including more of them than anyone could visit.

Formal verification

Also called Formal methods, Proof, Vericoding

Proving that code or a design meets a written specification for all inputs, not only the ones you tried, with a machine checking the proof. It covers what the spec says, under what the proof assumes, and nothing else.

A proof checker rejects an invalid proof however plausible it sounds, so it is one check an agent can't talk its way past. The cost moves to the spec. When one agent writes the code, the spec and the proof, one misunderstanding can sit in all three, and that is self-evaluation bias with a stronger label on it. It can also weaken the spec until it passes, the way it can edit a test. So someone else has to read the spec, usually you, and reading specs is a skill too.

Say it to your agent

“Verify one property of settle() in Dafny: the shares always add up to the bill, for all inputs. Before you write any proof, show me the spec in plain English and stop, because I will approve it. Then show the proof failing on a copy with the rounding step removed, and list every assumption and everything outside the proof.”

You can get some of this without a proof tool, by arranging the code so that the bad state has no way in.

Statechart

Also called State machine, Finite state machine

A drawing of a system as the states it can be in and the moves between them. Anything not drawn isn't allowed, so a refunded order simply has no arrow to shipped. A statechart adds states inside states, and regions that run side by side.

Flags and if-statements are the easy thing to generate, and they allow combinations nobody meant. One status and a table of moves makes those impossible to enter. A chart also gives you something to check an agent's understanding against, without reading the code.

Say it to your agent

“Replace isPaid, isShipped and isRefunded in src/order.ts with one status field and a table of moves: pending to paid or failed, paid to shipped or refunded, shipped to delivered. Any other event returns an error and changes nothing. Draw the table as a Mermaid stateDiagram in docs/order.md, and test every event in every state.”

All of that assumes the tests stay as they were. They are only files, though, and the agent can edit files.

Test tampering

Also called Reward hacking

Changing the tests so they pass, in place of fixing the code: skipping a test, deleting it, changing the expected answer, weakening the check, or making the code recognise the test's exact input.

The run goes green, and the summary says "fixed". A tampered run looks exactly like a real fix unless you read the diff of the tests or re-run the old tests against the new code. Both can be automated.

Say it to your agent

“Add a CI step: if a pull request changes files under src/ and also changes or removes existing tests, run the tests from main against the new code, and post the failures. Fail the job on any new test.skip. A person decides.”

The last defence is simple. If the agent can read the exam, the exam stops measuring anything. So keep some of it where the agent can't reach.

Holdout scenario

Also called Hidden scenario, Holdout

A test of what the software should do, kept where the agent can't read it or change it. The agent is judged on it afterwards, so it can't fit its work to it.

Everything else in this chapter can be seen and so optimised for. A holdout can't. It also catches a different class of failure: tests that are strong, and code that is consistent, but a job nobody asked for properly.

Say it to your agent

“Do not read anything under ../acceptance/. When you think you are done, I will run those scenarios and tell you which ones failed and what they expected, without showing you the code. Fix the behaviour, and do not guess at the tests.”

That is a lot of ways to spend a budget, and nobody can afford all of them on everything. So the last question is where the next token goes.

Verification spend

Also called Verification budget, Where the tokens go

Choosing where a limited budget of tokens and attention goes: mechanical gates, running the real thing, formal checks, or a model reading the code. Each sees things the others can't, so ask what this change could get wrong, and which check could see that.

An agent will spend on whichever check you ask for, and each one reports success in the same tone. Good practitioners disagree about where the money should go, and the evidence is thin. So the skill isn't knowing the right mix. It is being able to say what you bought, and what you still can't see.

Say it to your agent

“Before you spend anything on this change, list the ways it could be wrong. For each one, say which check could see it: types or lint, a test, a real run, a model check, or a read-through. Spend only on checks that could see something, and name any risk nothing here can see.”

Eval

Also called Evaluation

A test for an AI system: give it a task, grade the result, and do that many times, because it may answer differently each time. The result is a rate, not a pass or a fail.

It is how you test the agent's setup and not its code: did that AGENTS.md change help, or did it only feel like it? Without evals you are judging your harness from a few memorable runs.

Say it to your agent

“Before you change the system prompt, build an eval: these 20 tasks, 5 runs each, graded by the hidden scenarios in acceptance/. Run it on the old prompt and the new one, and show me both pass rates with their ranges.”

Do it for real

Reading gets you the words. This gets you the experience behind them, and something to show.

Get a real mutation score on code an agent wrote

This is the number that separates "the tests pass" from "the tests work". The before and after, with named survivors, is something you can put in front of a sceptical engineer.

  1. Ask an agent to write one small function with tests, in a throwaway TypeScript project with bun test.
  2. Run bun add -d @stryker-mutator/core typescript@6. Stryker core 10.1.1 crashed on TypeScript 7.0.2 when we tried it, so check that the version you get still needs the pin.
  3. Add a stryker.config.json with "testRunner": "command", "commandRunner": { "command": "bun test" } and "mutate" pointing at your file, then run bunx stryker run.
  4. Save the report. Paste the survivors back to the agent and ask it to kill each one or to show that it is equivalent.
  5. Run it again. Read the test diff, and check that it added assertions rather than deleting code.

Done when: Two Stryker reports, before and after, and a commit whose message names the survivors it killed and any it decided were equivalent.

Build a tamper check and watch it fire

A check you have never seen fail is one you only hope works. This takes under an hour, and it closes the easiest shortcut an agent has.

  1. In a project with tests, add a script that takes the test files from main, runs them against your working copy, and exits 1 if any fail.
  2. Add a check to the same script that exits 1 if the diff against main adds test.skip or test.only, or lowers the number of test() calls.
  3. Tell an agent to "make the tests pass" with a real bug in the code, and see what it does.
  4. Now edit a test yourself to make it pass: change an expected value, then skip it. Confirm that the script catches both.

Done when: A script in your repo, wired into CI or a hook, with a log of it refusing a tampered test.

Hide an exam from your agent

This is the idea behind StrongDM's scenarios, and behind the experiment on this site, at the smallest size that works. It gives you one honest number about your own harness.

  1. Pick one real feature, and write 5 to 10 scenarios for it in a folder outside the repo. Include the awkward ones: duplicates, things arriving out of order, empty input.
  2. Have an agent build the feature from a plain brief, with its own tests, without access to that folder.
  3. Run your scenarios against the result. Write down how many passed, alongside its own test count and coverage.
  4. Rewrite the brief using the right words for what failed, run it again in a fresh session, and record the new score.

Done when: A table with both briefs: the agent's own test count, its coverage, and how many hidden scenarios passed, plus the scenario file to point at.

Write one invariant, and have an agent try to break it

You don't need a proof tool to start thinking like one. Writing one sentence that must always hold is the part an agent can't do for you, and it is the skill every check above a test depends on.

  1. Pick a small function, or ask an agent for splitBill(totalCents, people) with its tests.
  2. By yourself, write one sentence that must always be true, such as: the shares always add up to the bill. Put it in a comment at the top of the file.
  3. Tell the agent: add fast-check with bun add -d fast-check, write one property test for that sentence and nothing else, and try to break it. Don't change the sentence. Paste the shrunk counterexample if you find one.
  4. Break the code yourself, for example by removing the rounding step, and run the test. If it stays green, the test can't fail, so fix that first.
  5. Put the code back, and commit the sentence, the test and the output of it failing.

Done when: A commit holding your invariant in plain English, a property test for it, and the pasted output of it failing on the broken version.

The build, stage 10 of 18

Do the tests really test?

A mutation score before and after, a floor it can’t fall under, a check for tampered tests, and an exam the agent has never seen.

About 90 to 150 minutes, on the same app as every other stage. We ran it first and show what went wrong.

Open stage 10 of the build

Gate 10: Tests

0 of 6 right

  1. 1An agent reports "312 tests pass, 100% line coverage" on a new pricing module. You change a + to a - in the discount calculation, and everything stays green. What does that tell you?

  2. 2An agent adds a Dafny proof to settle(), reports "verified for all inputs", and the checker agrees. Next day a bill of 100 split three ways comes to 99 in production. The spec it wrote says each share is at least 0. What happened?

  3. 3An agent fixing a failing test sends a pull request. The source file is unchanged, and the test's expected value went from 1800 to 1990. What is the right response?

  4. 4Your payment webhook code has green tests and a 100% mutation score, and it shipped an order after a refund, because a late event arrived out of order. Which conclusion holds up?

  5. 5A test fails about one run in five on identical code. The agent proposes retries: 3 in the CI config. What is the honest description of that?

  6. 6You ask an agent to raise a failing mutation score. It goes from 6 of 12 to 6 of 6, and the code is shorter. Which is the best next step?

Get every answer right to install it, and to put 5 files in your repo. Wrong answers cost nothing.

Next chapterDesign

The workshop

Name a word, or describe what you mean in everyday language.