knowledge: 3 verified testing-quality insights (value-preserving refactor tests, unasserted return fields, stale artifact baselines) - #49
Open
dch0202-rsquare wants to merge 2 commits into
Conversation
…downgrade 2 confidences to field-tested, correct 4 mechanism claims
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Knowledge flush — 3 insight(s)
Drained the 3 pending rows in
~/.dev-loop/queue/(session files5d6b4056,cea5f63a,ef805210; the other 10 queue files were already empty). All threecarried
domain: testing. None was dropped.Cross-Check: independent adversarial review (claude CLI headless,
--permission-mode plan) returned BLOCK on the first commit with 17 findings — 2 critical, 9 major, 6 minor; all were accepted and fixed in the second commit, the most serious being a source miscitation inherited from an existing page and twoverifiedconfidences downgraded tofield-tested.Confidence after review:
unasserted-return-fields=verified;value-preserving-refactor-assertionsandstale-artifact-baselines=field-tested. The first commit marked all threeverified; the review showedthat for two of them the cited docs support only the background mechanism, not the
central directive, so they were downgraded rather than defended.
Verified best-practice
1. A value-preserving literal→SSOT refactor cannot be guarded by an assertion that holds the config fixed →
field-tested.Claim: when the config value renders byte-identical to the literal you removed,
every assertion that holds the config fixed passes on the reverted-literal version
too; the separating input is the config value itself, so the test must vary it
through a seam a caller or operator reaches.
Sources opened: pytest monkeypatch
("All modifications will be undone after the requesting test function or fixture
has finished";
monkeypatch.context()applies patches "only in a specific scope"),unittest.mock ("you must
ensure that you patch the name used by the system under test"),
Stryker equivalent-mutants,
PIT basic concepts.
What the review changed here, and why it matters: the first commit called this "the
equivalent-mutant condition" and cited Stryker/PIT as its mechanism. That was
self-refuting — an equivalent mutant is one no input separates, while this page
then tells you to separate the versions by varying the config. The two are now
cited as a near analogy with the difference stated explicitly. Three further
corrections: the
try/finallyrationale was factually wrong (afinallyblock doesrun on assertion failure, so the honest reasons are "no restore code to review" and
"covers a patch applied in a fixture whose test body never runs"); the
wrong-patch-site failure mode is a misleading red, not a silent green (the
sentinel assertion fails on correct code); and the presence/absence halves were
described backwards — presence is the discriminator, absence is a supplement.
Confidence is
field-testedbecause no cited document supports the centraldirective; the only evidence for it is one in-house reproduction (manday renderer,
2026-08-05:
"DB ×%s" % E.DB_MULTrendered exactly the removed literalDB ×1.3,computed before the test was written; only the sentinel form reddened on the
reverted version).
2. A composite return's unread fields are unguarded, and cross-field invariants need their own assertion →
verified.Claim: diff the returned field list against the fields assertions mention, confirm
each absence with a per-field mutation plus the harness no-op control, then assert
the relations binding the fields across the input grid.
Sources opened: arXiv:2211.12003 (Alzahrani,
Spichkova, Harland, Application of property-based testing tools for metamorphic
testing) — "The core concept in MT is metamorphic relations (MRs) which provide
formal specification of the system under test";
hypothesis.works
— property-based testing as "the construction of tests such that, when these tests
are fuzzed, failures in the test reveal problems with the system under test that
could not have been revealed by direct fuzzing of that system";
PIT for the Survived-vs-No-coverage
distinction step 2 depends on;
abseil ch12.
This page keeps
verified: the two sources above back its central directive, andits field reproduction carries measured numbers (58 passing assertions over a
lo/sp/hireturn in whichloandhiappeared in none of them; four formulamutations left all 58 green while the no-op control survived, so the harness
discriminated; the invariant over the full discrete grid found 13 combinations with
sp > hi).Honest limit: Hypothesis's own
readthedocsquickstart does not contain adefinitional "property/invariant" statement — I fetched it, found none, and cited
the maintainers' article rather than inventing a docs quote.
3. A previously published artifact needs its generation dated and a row-level diff before it is a baseline →
field-tested.Claim: matching aggregates do not establish matching rows; date the artifact's
generation from its schema fields, and rebuild the before side by reverting only the
change under measurement when the generation differs.
Sources opened: SLSA v1.0 provenance
(provenance is "the verifiable information about software artifacts describing
where, when and how something was produced"; a build records "the specific git
commit that the URI resolved to as a dependency") — backs the stamping directive;
Jest snapshot-testing ("we would need to
fix the bug before re-generating snapshots to avoid recording snapshots of the buggy
behavior") — backs one edge row;
octopusinvitro
— a practitioner blog, not a primary spec, used only for the golden-master naming
caution.
What the review changed here: the first commit explained the failure with
non-injectivity of summation, which describes cancelling summands — but the field
evidence is a rollup parent excluded from the total, which was never a summand,
so no cancellation occurred. An engineer following the stated reason would hunt for
offsetting deltas, find none, and wrongly trust the total. The page now enumerates
three mechanisms and leads with exclusion (the one requiring no coincidence). The
generation-dating heuristic was also split: an absent field dates the file before
the field existed, a present-but-empty field dates it before the writer populated
it — two different conclusions the first commit conflated.
Confidence is
field-tested: the three central directives (dating by schema field,row-level full match, in-memory single-revert rebuild) cite nothing and rest on one
in-house reproduction (manday engine, 2026-08-05: counted-SP total 211.48 matched
HEAD exactly while the row diff found NEWRTB-2182 differing — 분석조사/0.19 vs
인프라/0.56 — with
dead: Nonedating the file before the classifier's lookbehindchange, and the issue being a rollup parent excluded from the counted total).
Retraction. The first commit's report asserted "Every URL cited below and on the
pages was opened in this session — no citation is carried over on trust." That was
false. Two of my new pages attributed the reachability–infection–propagation (RIP)
fault-detection model to
https://stryker-mutator.io/docs/mutation-testing-elements/mutant-states-and-metrics/.I had not opened that URL; I copied the attribution from an existing wiki page. The
cross-check flagged it and I then fetched the page: it contains the mutant-state set
and the metric formulas and says nothing about reachability, infection, propagation,
or RIP. Both citations are removed from my pages (the Stryker URL is retained on
unasserted-return-fieldsfor the mutant states it does document, and droppedentirely from
stale-artifact-baselines).Pre-existing defect flagged, not silently edited. The same miscitation exists in
wiki/testing/quality/differential-run-agreement.md:92("reachability, infection,and propagation (RIP) model for fault detection") and its directives at
:60and:83rest on it. That page is not mine to rewrite in this flush — the RIP model isreal but belongs to Ammann & Offutt, Introduction to Software Testing, not to
Stryker's docs. Flagged here and in
log.mdfor the owner.Existing-layer check
Pages read: testing-quality-tests-that-cannot-fail, testing-quality-minimum-case-set, testing-quality-harness-reverse-controls, testing-quality-differential-run-agreement, testing-quality-behavior-not-implementation, testing-quality-guard-shape-vs-consequence
Read in full: the first five.
guard-shape-vs-consequencewas read as its PR #47hunks plus its index line (partial — stated rather than implied). Screened by their
load whenlines inwiki/testing/index.mdwithout opening the body, having foundno trigger overlap: completion-predicates, injected-clock-duration-assertions,
write-path-assertions, checks-that-cannot-pass, spec-artifact-checks,
schema-additions-under-a-golden-gate. I also read
wiki/qa/index.mdend to end totest whether insight 3 belonged in
qarather thantesting(see Routing).Overlaps found, and merge-vs-create.
tests-that-cannot-failowns the generalrule all three insights descend from ("a test proves something only if it can
fail"), but its trigger is retrospective — reviewing an always-green suite. All
three candidates trigger at authoring time on a specific shape. The house already
resolves this shape as dedicated page + pointer row (
write-path-assertions,injected-clock-duration-assertions,schema-additions-under-a-golden-gateare allnarrower cases of the same page, each linked from its Edge cases), so I followed
that precedent rather than growing a page already at 105 body lines. Merged instead
of duplicated:
tests-that-cannot-fail+3 Edge rows,minimum-case-set+1 Edge row(its "assert an observable outcome" is underspecified when the outcome is a
composite — the fields and their invariants),
differential-run-agreement+1 Edgerow (its subject is two live runs; a stale artifact as one side is the adjacent
case).
Conflict found, and the resolution tightened after review.
behavior-not-implementationstep 2 asserts "a refactor that preserves behaviorkeeps every test green", which pulls against insight 1's test — one that goes red
when someone re-inlines a literal, a change with identical output. I resolved it
with a condition-dependent Edge row on both pages rather than overwriting either.
The cross-check then attacked my first wording as a rationalization, correctly: it
justified the test by "configurability is behavior … through the seam an operator
controls", while another edge row extended the same test to a module-local
constant no operator can set — where re-inlining removes no observable capability
and the assertion becomes exactly what
behavior-not-implementation:41ordersdeleted. Generalized, that would let any implementation detail be relabelled a
capability and would quietly remove step 2's diagnostic force. Both rows now carry
the boundary: the value must be settable through an interface a caller or operator
reaches without editing source (config file, env var, DI parameter, CLI flag);
when it is not, step 2 stands unchanged and the guard moves to a static check. The
module-local edge row was rewritten to route there instead of asserting the
substitution test "still applies". That page's step 2 text is untouched, and its
last_verifiedwas returned to2026-07-10— I added an edge row withoutre-opening its three sources, so bumping the date would have claimed a verification
I did not do.
Related links are now genuinely bidirectional for all five adjacent pages (the
first commit left two one-way:
minimum-case-set→ value-preserving andharness-reverse-controls→ stale-artifact-baselines; both back-links added).One-way references remain, by design, to
checks-that-cannot-pass,write-path-assertionsandbackend-common-change-impact-call-site-enumeration.Verified programmatically: every
related:id and inline[page-id]referencerepo-wide resolves; all three new pages are listed in
wiki/testing/index.md;every touched page's body is under the 120-line limit (max 105); template sections
and frontmatter keys present; no banned vague qualifier in a directive sentence (one
"usually" was caught and rewritten as the condition that decides it). The checker
was itself controlled — injecting a bogus
related:id and a banned qualifier madeit report both, and it returned to PASS after restore. Note the limit that mattered:
that checker validates link resolution, never whether a source says what a page
claims, which is why the RIP miscitation above needed the independent review to
surface.
Open-PR check
gh pr list --repo choiyounggi/dev-loop --state open→ #47(
knowledge/dch0202-20260806-130040, labeldev-loop:knowledge) and #48(
feat/tmux-coordinator-gaps, code not wiki). I fetched #47's head and diffedorigin/main...origin/knowledge/dch0202-20260806-130040 -- wiki/in full.tests-that-cannot-failchange is a bats/bash-3.2[[ ]]row plus three sources; no overlap of trigger or directiveTextual adjacency handled rather than ignored: #47 also edits
wiki/testing/quality/tests-that-cannot-fail.mdandwiki/testing/index.md, the twofiles this flush edits too. My edits were placed away from its hunks (Edge-cases
table and the
related:line; three appended index rows below the last row ittouches), and where we both bump
last_verifiedontests-that-cannot-failI setthe identical value it sets (
2026-08-06, today) so the two branches convergeinstead of conflicting. Whichever merges second should still be re-read at merge
time — the claim here is that no hunk overlaps, not that git is guaranteed silent.
Routing decision
INDEX.mdroutes all three to testing ("writing or structuring automatedtests: level choice, cases/assertions…"), and within it to the existing
quality category. No new category: quality already holds the
"is this assertion capable of failing / may I cite this verdict" family
(
tests-that-cannot-fail,harness-reverse-controls,differential-run-agreement,spec-artifact-checks), which is precisely what all three are.testing/quality(new page)value-preserving-refactor-assertions.md—testing-quality-value-preserving-refactor-assertionstesting/quality(new page)unasserted-return-fields.md—testing-quality-unasserted-return-fieldstesting/quality(new page)stale-artifact-baselines.md—testing-quality-stale-artifact-baselinesRejected alternatives, with the reason each was rejected:
minimum-case-set: that page selects cases over theinput space (normal/error/boundary per behavior); insight 2 is coverage of the
output shape and the relations inside it. Distinct axis, so it became a page and
the two are cross-linked — the same split the house already made for
write-path-assertions.qadomain: I readwiki/qa/index.mdin full.qaownsrelease-process quality (gates, regression scope, deliverable documents) and
explicitly sends automated-test-code concerns to
testing/. Insight 3 is aboutwhether a comparison is valid evidence, which is what
testing/qualityalreadyhosts for non-test-code artifacts (
differential-run-agreement,harness-reverse-controlsgovern reports and PR bodies, not only suites). Routedto
testing/qualityfor that precedent, with arelated:link toqa-deliverables-generated-artifacts-as-deliverable-source.tests-that-cannot-fail: rejected on the page's ownconstraint. It is at 105 body lines against a 120 limit and knowledge: bats/bash-3.2 assertion trap + 4 orchestration/guard edges; 5 duplicates retired #47 adds to it; three
full cases would push it over and bury three distinct triggers inside a page whose
routing line is retrospective auditing.
Reviewing this PR
The two
field-testedpages are the ones to read hardest: their central directivesrest on single in-house reproductions, described on each page, and are the parts no
external source backs. If you would rather not carry a page at that confidence,
stale-artifact-baselinesis the most self-contained one to drop — the other two arecross-linked from four existing pages. The
differential-run-agreement:92RIPmiscitation is pre-existing and left for you to decide on.