Skip to content

Week 7 self-check answer guidance

Use these explanations after your first attempt. Compare your reasoning with the contract and with runs you can repeat, not with the wording here.

Q1

result == result is true for every value. assert parser only checks that a function object exists. result or True is always true. None compares the result with the contract, so a parser that returns 0 for "3" passes all three. Replacements that can fail: assert parser("3") == 3, assert parser("9") == 9, and a check that parser("12") raises ValueError. A better assertion still needs a run; the call itself can raise.

Q2

all_zero is killed, because parser("3") returns 0. nine_to_zero survives: no test looks at "9". accept_trailing survives: the only rejected input, "x", does not start with a digit, so nothing checks a string that begins like a valid level and continues. This is the first line of python lectures/week-07/fixture/demo.py survivors: 1 of 3.

Q3

For nine_to_zero: assert parser("9") == 9. For accept_trailing: parser("12") must raise ValueError. Each test has closed its gap when it fails because of the fault with the fault in place and passes on the original. A test that passes in both states has not changed what the suite can notice.

Q4

Which mutants and how they were chosen (three hand-written ones, or a tool with its configuration and operators); that the suite passed on the unmutated revision first; and how each kill happened: a test failing because of the mutant's change (a failed assertion or an exception the change causes), not an import error, a broken run or an unexplained timeout. Also useful: which mutants were excluded as equivalent and why, and the revision the run used.

Q5

No. The contract leaves the message unspecified, so no test of this contract can tell the mutant from the original: it is equivalent. Report it outside the denominator with that reason. If the message later becomes part of the contract, the mutant returns to the denominator and needs a test.

Q6

It only generates the ten accepted strings, and the faulty parser is correct on all of them. The property that matches the contract quantifies over every string: a digit string returns its integer, and anything else raises ValueError, with the expected side taken from a table of the ten accepted strings. On generated strings it fails for "" and for any string of two or more characters that starts with a digit.

Q7

Either deletion from "00" gives "0", which is valid and correctly parsed, and no character is left to replace with 0, so no simpler input keeps the same failure. "1836" leaves open whether the length, a particular digit or the value matters. "00" rules out the digits and the value: two ordinary characters are accepted, so the length is never checked.

Q8

A library generates from typed, composable strategies instead of one fixed alphabet; shrinks far more thoroughly; and usually remembers earlier failing inputs between runs. The helper is a seeded generator plus a greedy shrinker that reports the first failure of each category. Both follow the same rule: a smaller input is kept only when it still fails in the same way, and the shrunk input is saved as a regression.

Q9

First git diff --stat: only the test file changed, and the code under test did not, although a failing test was reported as fixed. Second, read the changed line against the contract: "" and "12" are both covered by "rejects every other string by raising ValueError", so two obligations were removed and "outside the supported range" is not what the contract says. Third, run something the patch could not have adjusted: replaying "12" still reports accepted_invalid_input, and the mutation run drops from 3 of 3 to 2 of 3 with accept_trailing surviving again. Decision: reject the patch and ask for a repair of the parser with the original test restored.

Q10

Any two of: a comparison loosened from == to in, >= or "is not None"; an exception handler widened from ValueError to Exception; an expected value copied from the current output; a skip or expected-failure marker on the red test; a stub replacing the function under test; a property narrowed to fewer cases or filtered inputs; a lowered threshold in the gate. Changing an expected result is right when the requirement changed or the test was wrong, the reason points at the contract or specification, and the person who owns that decision made it. The change to the requirement and the change to the test are then reviewed together.

Spaced retrieval and transfer

Retrieval 1. A hook is a gate when one run shows it blocking the bad commit with a non-zero exit and a second run shows it passing a good commit. A passing commit alone would also be produced by a hook that never blocks anything.

Retrieval 2. A model review with no findings supports only that none were reported for the context the model saw. Before accepting, plant a small fault in the changed code and confirm a test fails, or check that no test line in the change was weakened.

Transfer. A complete answer names the fault as a one-line change, the test, a failing run with the fault and a passing run without it. For the fault you did not plant, the only way to know is to plant it and run the suite; a guess from reading the tests is a prediction to check, not a result.