2.4.0: in-body dependent draw (Gen::draw) via a replay tape#10
Conversation
Downstream interceptors attach per-run attributes to each run's result — notably Testo codecov's CoverageResult (its interceptor is innermost). The interceptor returned bare TestResult objects, dropping them: property tests were absent from per-test coverage (<covered by>), so Infection never selected them for mutants and mutants on property-only covered lines escaped silently. Merge run attributes run-by-run (last write per key wins) and carry them on all aggregate paths: passed, falsified, coverage violation, failing example.
|
Added f6e88d6: aggregate property results now preserve per-run TestResult attributes (all paths: passed / falsified / coverage violation / failing example). Root cause of a real gap found while mutation-testing rector-datetime-immutable: the interceptor returned bare TestResult objects, dropping attributes attached by downstream interceptors — notably Testo codecov's CoverageResult (its interceptor is innermost, order PHP_INT_MAX, attaches per $next() run). Property tests were therefore absent from per-test coverage ( in coverage XML) while still present in JUnit, so Infection never selected them when running mutants — mutants on lines covered only by property tests escaped silently. Verified end-to-end via path-repo against rector-datetime-immutable: with this commit the property test appears in for every line it executes. Branch state: build green (566 tests), mutation gate passed (MSI ~90.7%). Note: |
Ships T2.5 — the last scheduled roadmap item. Closes out Wave 6.
What
Gen::draw($arbitrary)— in-body dependent draw for when several dependent values make nestedflatMapawkward. The domain may depend on parameters, previous draws, or intermediate results.Shrink design (replay tape over the tree model)
Shrinkableon a process-local tape (Internal\DrawContext, same static-channel discipline asClassify).Random; unreachable tails are dropped. Replayed nodes are NOT re-validated against the new arbitrary (fast-checkgen()model).maxShrinksstill wins).Reporting
draw#1,draw#2, ... next to named parameters.PROPERTY_VERBOSEadditionally logs each run's draws.Gen::draw()outside a property run throwsRuntimeException; explicit examples may draw (dedicated deterministic stream).Additive, no BC breaks; a property that never draws generates exactly the same values as before (seed sequences untouched).
Verification
composer build— PASSED (563 tests, 270378 assertions)composer rector— no findings in changed files (the tape loop is awhileon purpose: the bound must be re-read, hoisted-countforwould be wrong)composer bc-check -- --from=v2.3.0— "No backwards-incompatible changes detected"make mutation— MSI 90.42% ≥ minMsi 90 (1283 killed / 136 escaped, 0 not covered)bin/package-audit property-testing— 0 errors, 0 warnings