Chapter 06 · Reps

Test, Integrate, and Cut — Reps

← Back to Chapter 6

Chapter 6 — Reps

These reps are not warmups around the milestone. In order, they are Milestone 6. When the last one finishes you have a tested, integrated, measured, security-reviewed, tagged release candidate — and a written record of everything you decided not to fix.

Ground rules

  • Work on YOUR project. PantryPilot and TraceLens are examples. Every rep operates on your real requirements, your real seams, your real requirement IDs.
  • Derive tests from the requirement, not the code. Open docs/requirements.md first. If you have already read the implementation, have the assistant write the case from the requirement text alone.
  • Log the defect before you fix it. Every one, including the thirty-second fixes. The log is graded, and it is the only evidence you found anything.
  • Two columns, always, plus an estimate. Severity, priority, and hours. Severity is a fact about the product; priority is a decision about your calendar; the estimate is what makes the queue fit.
  • Nothing goes in a document you did not verify. Advisory IDs get looked up. Performance numbers get measured. “Should be fine” is not evidence.
  • Commit as you go. Each artifact lands with a dated commit that names the requirement or defect ID. docs: and test: are commits too.
  • Write the reflection. A rep is not done until the two to four sentences are written. Keep them in docs/hours-log.csv notes or a scratch file; the honest ones become your Week-8 retrospective.

Monday — the promises

Rep 1 — Scope, out of scope, and six exit criteria

Copy code/test-plan-lite.md into docs/test-plan.md. Fill sections 1, 2, and 5 today, before you look at how the build is doing.

Scope:        requirements ____ through ____, at commit ____________
Out of scope: 1. ______________________ because ______________________
              2. ______________________ because ______________________
              3. ______________________ because ______________________

Exit criteria (every line checkable by a stranger, without asking you a question):
  1. ______% of Must requirements have >= 1 passing acceptance test
  2. Zero open defects at severity ____ or above
  3. ______________________________________________________________
  4. ______________________________________________________________
  5. The full suite runs from `./script/test` and passes in CI
  6. ______________________________________________________________ (a number from your NFRs)

Reflect: Read criterion 6 back. Could a grader check it without you in the room? If not, it is an adjective wearing a number’s clothes. Rewrite it.


Rep 2 — One acceptance criterion, one test case — then the boundaries

Pick three acceptance criteria: one you are confident about, one you are unsure about, one you have never exercised. Write a full test case for each.

TC-____  Verifies: ____-AC__   Level: unit / integration / acceptance   Data: ________
Preconditions: ______________________________________________
Steps:  1. ______________  2. ______________  3. ______________
Expected: ______________________________ (an observable value, not "it works")
Fails if: ______________________________ (the specific bug you are hunting)

Now take whichever of the three contains a number, a date, a length, or a count, and produce the partition table. Write a test at every boundary value, then run them.

| Partition          | Representative | Boundary values worth a test |
|--------------------|----------------|------------------------------|
| below the range    |                |                              |
| inside the range   |                |                              |
| above the range    |                |                              |
| absent / null      |                |                              |

Expect at least one boundary test to fail. If none do, widen the partitions — you have only tested the middle of each class.

Reflect: Which of the three criteria was hardest to turn into a test case? A criterion you cannot test is usually a criterion that was never testable — a Week-2 defect you just found for free. Log it.


Rep 3 — Build the matrix and run the honest number

Copy code/traceability-matrix.csv into docs/traceability.csv and replace the sample rows with yours: one row per acceptance criterion, with its test case ID, level, status, and defect ID if it is failing. Requirements with no test appear in the matrix as gaps — do not quietly omit them.

python3 coverage_report.py docs/traceability.csv

Use code/coverage_report.py. Record four numbers in docs/test-results.md: total requirements, verified requirements, verified-requirement coverage, verified-Must coverage.

Reflect: Write your verified-requirement coverage down before you fix anything. Most students see 30% to 60% the first time. If more than two Must requirements come back unverified on Monday of Week 6, that is a scope signal, not a testing signal — flag it now and take it to Rep 10.


Tuesday and Wednesday — execution

Rep 4 — The first full acceptance pass, by hand

Ninety minutes, unscripted after the first thirty. Drive your own software the way a hostile, impatient, confused user would: submit empty forms, double-click everything, go back, refresh mid-operation, paste 10,000 characters, type an apostrophe into a name, set a date to today and then to blank.

Log every defect as you find it, with all seven fields from code/cut-kit.md. Do not stop to fix anything. Fixing is Rep 9.

Defects found in the acceptance pass: ____
Of those, ones I already suspected:   ____
Ones that would have shipped:         ____

Reflect: If this rep found nothing, the rep went wrong, not the software. Go back with the hostile data — Unicode, emoji, O'Brien, a 10,000-character field, a JPEG renamed .csv — and try again.


Rep 5 — One integration test per Tier 1 seam

Open the component diagram in docs/architecture.md and list every seam. Mark the Tier 1 ones: crosses a process, network, or storage boundary and sits on an acceptance path. You will usually find two or three. Write a real integration test for each — not a unit test with mocks on both sides.

Then hunt the seven failure modes on purpose:

[ ] contract drift   — send a payload missing an optional field; what happens?
[ ] unit mismatch    — grams/ounces, seconds/ms, cents/dollars: assert the unit
[ ] time zone        — an item that expires "tomorrow" for a user in another zone
[ ] identity         — same logical record submitted twice; duplicate or 409?
[ ] ordering         — call B before A has run; does it fail loudly or silently?
[ ] error semantics  — make A fail; does B report failure or render "no results"?
[ ] partial failure  — kill the process between two writes; is the invariant broken?

Reflect: Which probe found a real bug? Write the defect ID and one sentence on why six weeks of unit tests never saw it.


Rep 6 — Measure a target, then break a dependency

Pick one non-functional requirement with a number in it. Generate realistic volume — hundreds of records, not seven. Run at least 30 requests. Record p50 and p95, not the average, with the method beside them, in the performance section of docs/test-results.md.

| ID | Target | Method (load, env, sample) | p50 | p95 | Verdict | Action |
|----|--------|----------------------------|-----|-----|---------|--------|

If it misses, make exactly one fix and re-measure. Record both numbers.

Then take your riskiest third-party dependency and make it fail four ways — slow, down, rate-limited, changed response — and record what a user sees each time. Implement graceful degradation for at least one: a timeout, a fallback path you control, an honest message.

Reflect: Before this rep, what did your app do when that dependency was down? “It hung,” “it crashed,” and “it showed a blank page” are three different answers and only one of them survives demo day.


Rep 7 — The ninety-minute security pass

Set a timer. Work four areas and fill the evidence column of the security section in docs/test-results.md with something re-runnable or re-readable.

git grep -nIE '(AKIA[0-9A-Z]{16}|BEGIN [A-Z ]*PRIVATE KEY)'
git ls-files --error-unmatch .env 2>/dev/null && echo "TRACKED - fix this"
#AreaThe questionEvidenceFindingDisposition
1SecretsAny credential in the repo, its history, a log, or a screenshot?
2AuthorizationFor every object a user can name, is ownership checked server-side on every request?
3InputIs every externally supplied value validated and parameterized before it reaches a query, shell, path, or template?
4DependenciesDoes any dependency carry a published advisory, and is the vulnerable path reachable?

Do area 2 by hand: log in as user B and request user A’s object by ID, directly, not through the interface. Verify every advisory identifier at https://github.com/advisories or https://osv.dev/ before it goes in the table.

Reflect: Did the server check ownership, or did it trust the identifier? If it trusted it, that is an S1 and it gets an ID today. If it checked, say how you proved it — a test, not a memory.


Thursday — judgment

Rep 8 — Count the hours, then make the queue fit

Before you touch the queue, write the budget:

Hours left in Week 6 after the acceptance pass ..........  ____
Defect reserve protected inside Week 7 ..................  ____
                                                          -----
Discretionary build hours left in the whole project .....  ____

Now take ten open defects. Assign severity, priority, and an hour estimate to each, every one with a one-line reason. Then produce two lists whose first list sums to no more than the number above.

FIX ORDER (fits inside the budget):
  1. ____ (__ h)  2. ____ (__ h)  3. ____ (__ h)  4. ____ (__ h)   total: ___ h

SHIPS AS A KNOWN OPEN DEFECT (with the workaround a user needs):
  ____  workaround: ______________________
  ____  workaround: ______________________

Reflect: Which defect did you want to fix and cannot? Write one sentence defending that decision to a user affected by it. If you cannot write that sentence, re-triage — you got the priority wrong.


Rep 9 — Red, green, prove it

Pick the top defect from Rep 8. Do the loop in strict order, with separate commits.

1. Write the failing test.  commit: "test: TC-___ reproduces DEF-___"
2. Fix the code.            commit: "fix(FR-__): ______ — closes DEF-___"
3. Prove the test is real:  git checkout HEAD~1 -- src/   then run ./script/test
                            It must be RED. Then: git checkout HEAD -- src/
4. Name the regression test in the defect log entry.

Repeat for every defect in your fix order.

Reflect: Did step 3 come back red on the first try? Report honestly. This is the step everyone skips, and it is the one that catches tests that verify nothing.


Rep 10 — Three change requests, and the cut you have been avoiding

Take three real change requests — from your advisor, a user, a demo conversation, or your own head at 1 a.m. Write each as its own file in docs/change-requests/, named CR-0NN-<short-slug>.md, using the template in code/cut-kit.md.

Cost:          ___ build + ___ test + ___ doc = ___ h;  ___ h discretionary remain
Blast radius:  FR-___ / NFR-___, modules ___, interfaces ___, tests ___, docs ___
Risk:          accept -> ___________ ;  refuse -> ___________
Disposition:   ACCEPT | DEFER -> ______ (sized) | REJECT (reason: ______)

At least one must be a REJECT with a reason a stranger would accept, and at least one a DEFER with a named destination and a size. If Rep 3 left you with more than two unverified Must requirements, one of these three is the withdrawal of an inherited requirement — the Fast-Start brief’s promise that never became yours. Mark anything cut Deferred in docs/requirements.md with the date and the CR reference. Do not delete the row. Then add one row per CR to the change table at the top of CHANGELOG.md.

Reflect: Which one was hardest to refuse, and was the difficulty about the project or about the person who asked? Name it plainly. That is the muscle this week trains.


Rep 11 — Grade the assistant’s test cases

Pick one requirement. Give an assistant the requirement text and acceptance criteria only — explicitly tell it not to look at your implementation — and ask for ten test cases with expected results. Audit all ten against your specification.

| # | Asserts the right thing? | If not, what went wrong?                        |
|---|--------------------------|-------------------------------------------------|
| 1 |  yes / no                | change detector / empty assertion / invented API |
|   |                          | / confident wrong oracle                         |

Count the wrong ones. Then run the same prompt again with your code in the context and count again.

Reflect: Report both counts. Was the second run worse? It usually is — that is the change detector, and it is why the requirement, not the code, is the right input. At your measured error rate, how fast are you actually allowed to accept generated tests? Record the tool and this use in docs/ai-usage.md.


Rep 12 — The Coverage & Cut Planner, run twice

Run the widget on the chapter page. First pass: give it a fantasy budget of thirty hours. Second pass: give it the real number from Rep 8.

Run 1 (30 h):  fixed ___ / shipped open ___ ; last item above the line: __________
Run 2 (real):  fixed ___ / shipped open ___ ; last item above the line: __________
Items that moved from "fix" to "ship open" between the runs: ___

Reflect: That list of moved items is exactly what you are cutting this week. Did seeing it change any priority you had already set? Copy the resulting known-issues entries into CHANGELOG.md.


Done? One Last Thing.

The release-candidate dress rehearsal. End to end, in one sitting, exactly as your Week-8 grader will.

  1. Check yourself against your own exit criteria from Rep 1, line by line. Tick the ones you meet. Do not edit a criterion to match the result. For every miss, either fix it or write the known-issues entry that says what ships and why.
  2. Commit everything. Confirm git status --porcelain is empty.
  3. Clone your own repository into a fresh directory — a clone, not a pull, somewhere else on disk. Start a timer.
  4. Follow only what README.md says: ./script/setup, then ./script/test. Do not fix anything from memory.
  5. Every place you had to deviate from the README becomes a documentation defect with an ID. That is Chapter 7’s work, and now you have a real list instead of a guess.
  6. Break your riskiest dependency and confirm the degradation path from Rep 6 still holds.
  7. Stop the timer and record the run in docs/test-results.md: commit SHA, date, command, pass/fail counts, duration, and the four coverage numbers.
  8. Tag it: git tag -a v0.9.0-rc.1 -m "Release candidate 1: tested increment, Milestone 6" and push the tag.
  9. Commit: milestone 6: tested release candidate, defect log, change log.

If that clone runs clean and your exit criteria are either met or honestly annotated, you have done real verification — the thing most capstones only claim — and Week 7 becomes writing rather than rescuing.

Up next: Milestone 6