Repository navigation
v1.4.0 - Trustworthy verdicts #87
ericodx
announced in
Announcements
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Five separate ways the tool could report a wrong number without saying so are fixed. A failing suite no longer makes every mutant look killed, cached verdicts no longer outlive the code they were measured against,
--no-cacheno longer leaves a cache behind, and cleanup from a timed-out mutant no longer kills the next one. SPM packages now test their mutants in parallel.What's new
Baseline validation (SPM)
BaselineError, naming the tests that failed, the timeout that stopped the suite, or the output it died with$TMPDIR, since a test deriving paths from#filePathpasses in place and fails there__SWIFT_MUTATION_TESTING_ACTIVEin the environment cannot select one for the run that must have none--keep-logs <directory><directory>/<mutant-id>.logParallel execution for SPM packages
.xctestbundle directly rather than throughswift test, which takes a lock on.buildand forced workers to queue--concurrencyis honoured for SPM againBug fixes
Verdicts
Killed.validateSPMBaselineran the unmutated suite and discarded the result; one reported run showed 260 killed and 0 survived, with the true survivors invisible (SPM: baseline test result is discarded, so a failing suite reports every mutant as Killed #66)Cache
fileContentHashfell back to the file path for every schematizable mutant — a constant — so stale verdicts were replayed (Cache key hashes the file path, not its contents, for schematizable mutants #79)Killedverdict is now dropped when the test that killed it changes. The killer file was stored absolute and compared against project-relative keys, so the comparison was never true (Cache: Killed verdicts are never invalidated by test-file edits (absolute vs relative path mismatch) #67)--no-cacheno longer writes a cache. It guarded only the read side, so a run told not to use the cache still left one behind for the next run to replay (--no-cache disables cache reads but still writes; the next run silently replays the results #68).unviableand skipped by every diff, so a spurious one could never be cleared (Crash verdicts are never invalidated, so a spurious one is permanent #80)Configuration
--concurrencyis resolved to what a run can actually use. Xcode schemes targetingplatform=macOSget one worker, as do XCTest runs, rather than reporting a number the simulator pool will not honour (SPM: parallel workers serialize on SwiftPM's .build lock, and the wait counts against each mutant's timeout #70)--concurrency 9against an SPM package printed✓ 9 simulators readyArchitecture changes
BaselineErrorProjectRelativePathProcessTreeTimeoutEscalationTestBundleInvocationswift testMutantLogWriter--keep-logsis givenMutantDescriptorgainssourceContentHash— the hash of the unmutated file, computed at discovery where the contents are already in hand rather than read back once per mutant. The cache key is built from it, alongside the file path: content alone collides for two byte-identical files, whose mutants are not interchangeable because they compile into different places.RunnerEvent.simulatorPoolReady(size:)becomesworkersReady(count:usesSimulators:)— the reporter can no longer call a worker a simulator when there is no simulator.SimulatorPoolhands out every configured slot when it has no simulators to clone, instead of a single one.Both testing libraries are run for SPM mutants, in the order
swift testruns them and under one shared deadline. A package may hold XCTest classes and Swift Testing functions at once, and running only the configured one silently skips the other's tests.Upgrade notes
Existing caches are invalidated. The cache key changes shape, so the first run after upgrading re-measures everything. That is the point: the old keys were built on something that could not detect the change they existed to detect.
A failing suite now ends the run. Previously the run continued and produced a report. If your suite does not pass inside the sandbox — most often because a test derives paths from
#filePath, which resolves to$TMPDIRthere — the run will stop and name the tests to fix.--concurrencybehaves differently. SPM packages honour it, where before it was accepted and ignored. Xcode schemes onplatform=macOS, and XCTest runs, resolve it to 1 rather than reporting a figure the pool will not honour.Validated against a real project
Run against a 116-file package with 944 tests and compared mutant-by-mutant against a report from v1.3.0.
Discovery is unchanged: the same 949 mutants at the same positions, none exclusive to either version. 50 verdicts (5.3%) differ.
Scoped to one directory and run at matching concurrency, 32 of 63 verdicts changed — 20
Unviable → Killedand 2Unviable → Survived. Those last two matter most: real surviving mutants that were hidden behind "not testable", which is a test gap the tool was not reporting.Four
Crash → Survivedare false kills from the cleanup defect, now gone.Test coverage
Known issues
Crashrather thanKilled, because the parser looks for a line shape the library does not emit. The score is unaffected, but the killer test file is not resolved (Swift Testing failures are reported as Crash instead of Killed #83)SwapTernaryproduces mutants that cannot compile, so none is ever testable (SwapTernary produces mutants that cannot compile, so none is ever testable #82)Unviable(Builds are bounded by the test timeout, so a slow build is recorded as Unviable #84)Unviableand the cause is not yet diagnosed (60% of mutants are reported Unviable — find out why #85)Thanks
To @jwp23, who reported #66, #67, #68, #69 and #70 — the five defects this release is built around. Each came with measurements, a list of what had been ruled out, and in #66 a negative control: an assertion removed on purpose so a known true survivor could be shown still coming back Killed. That is what made them actionable without having to reproduce them first.
Requirements
Installation
See the Installation Guide for Homebrew, pre-built binary, and build from source instructions.
This discussion was created from the release Trustworthy verdicts.
All reactions