Adopting an existing suite

Copy Markdown View Source

Surfex's process (spec §18) assumes new work: a test is written, fails, and passes once the code exists, and that red→green is the evidence a relation rests on. An established project's tests already pass. They can't honestly go red, so without help every relation would need a review before Surfex reports anything useful, and again after each refactor.

adoption: in .surfex.exs decides how much of the existing suite is taken on trust (spec §18.1).

Trust or re-evaluate

SettingUse it when
:reevaluate (the default)the suite is new, small, or nobody can vouch for it; or the project wants every relation earned
:trustthe suite has been kept honest for a long time: written test-first, reviewed, run in CI on every change
[trust: globs, reevaluate: globs]a well-kept core beside tests nobody has read in a while

Per area, the globs lie within tests: and don't overlap. A test matched by neither is re-evaluated:

adoption: [trust: ["test/core/**/*_test.exs"], reevaluate: ["test/legacy/**/*_test.exs"]]

Trust is a statement about the tests, so make it where you'd defend it. Re-evaluating a test later is always possible. Trusting more later is not.

The baseline

Under trust, adoption is: tag, run green, take the baseline.

# 1. Write @tag verifies: on the tests that verify each spec unit: the review work.
mix test
mix surfex.baseline --note "test-first since 2023, reviewed in every MR"
mix surfex.confirm --evidence

Tag first. The baseline adopts the verifies: tags already written; it doesn't create them, and it is one-shot. A tag added afterwards is an ordinary claim, proposed until its test fails and passes or someone reviews it, one at a time. So the tags decide what the baseline is worth. With none, mix surfex.baseline refuses, unless --no-tags says you mean to baseline test versions alone and tag later at that per-tag cost. It ends by reporting what it adopted: the trusted test versions, the verifies relations, and the spec units left without one.

What it is. A record, per trusted test version, that the version counts as if it had discriminated, plus that test's verifies: tags as relations with basis baseline. confirm --evidence then carries the code each baselined test exercises (implements, basis baseline). The note says why the suite is trusted; it stays in the log.

What it isn't.

  • It isn't evidence: reports count baseline relations separately, naming the mode.
  • It isn't repeatable: it is one-shot, so widening adoption: later trusts nothing new.
  • It doesn't vouch for tests that aren't green at the time it is taken. Surfex refuses until they are.

From trust to evidence

The baseline only shrinks. Each relation leaves it the first time its test discriminates for real: a run that fails and then passes against different code, at the same test version. confirm --evidence records that red→green, and the relation moves to basis evidence. Ordinary bug-fix work does this over time. Nothing has to be scheduled.

When the backlog should end, mix surfex.status --no-baseline (or baseline: :fail in .surfex.exs) fails while any relation still rests on the baseline.

Code that deviates from the spec

A suite that passed green can still pass while the code deviates from the spec. Writing the spec's tests turns those deviations up: the test is right, the code is wrong. Tag each such test with the reference to what will fix the code, beside the skip that keeps the suite green:

@tag verifies: "free-over", deviation: "#119", skip: "known deviation (#119)"
test "delivery is free over the threshold" do

Record its verifies on its red run as usual. Status lists the unit under Deviating with its reference, and its proposed relations don't fail. The gate can be joined while the deviations are fixed. Completeness counts the unit incomplete (deviates (#119)), and RELATIONS.md keeps the ledger. Run the deviation tests with their skips included now and then (mix surfex.test --deviations, then mix surfex.status --evidence). A deviation test that passes fails the status as stale. Meanwhile mix surfex.confirm --evidence doesn't validate an implements to the deviating unit or to a section holding it: it lists each as held back by the deviation, and validates it on the first run after the fix. When the fix lands, drop the tag and the skip, and validate as for any change. A release can hold every deviation with mix surfex.status --no-deviations.

What changes cost afterwards

ChangeTrusted testRe-evaluated test
Refactor the code, tests still greenconfirm --evidence re-confirms it as baseline; no reviewit needs a red→green, or a review (mix surfex.validate)
Edit the testthe new version isn't baselined: a red→green, or a reviewthe same
Change the spec unitreview the test against the new text, as alwaysthe same
A test's first red→greenits relations move to evidencethe same
Narrow adoption:its baseline relations are reported unvalidated: the backlog to review—
Add a testthe normal process: fails first, then passesthe same

Trust only saves work on the most common change, a refactor under green tests. Everything else costs what it would without adoption.

Moving to claim grain later

A baseline taken while relations sit on sections isn't redone when the project moves them to its claims: mix surfex.migrate carries a section relation's baseline to a claim the same baselined test verifies. See the guide "Migrating to claim grain".