Repository navigation
Conversation
Each test process that reads a skip list writes skipped.tsv beside its output (`framework\tmodule\tsuite\tname`): the XCTest tests it removed, once the removal took effect, and the Swift Testing tests the trait cancelled. A reader can then tell a listed test that was skipped from one that ran anyway: a suite without the trait, Swift before 6.3, or an XCTest without -setTests:. The file is created empty as soon as the list is read, and removed when a line can't be written, so a missing file never reads as "nothing skipped". It's only written with TEST_COVERAGE_ATTRIBUTION_DIR. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
Follows #38 (Swift Testing skipping), which merged while this was in progress, so this targets
main.What changed
Each test process that reads a skip list now writes
skipped.tsvunder$TEST_COVERAGE_ATTRIBUTION_DIR/<pid>/. The file lists the tests that process actually removed (XCTest) or cancelled (Swift Testing). It has one line per test, tab-separated:framework\tmodule\tsuite\tname. The framework isxctestorswift-testing, and tests are named as the records name them, for exampletestSkippedThrowingfor an XCTest test.testSkippedThrowingfortestSkippedThrowing() throws), the same as inrecords.bin.suite_without_skipped_testsreports the tests it removed only once the removal has taken effect: after-setTests:runs, or once the empty replacement suite exists. If an XCTest lacks either, the tests run and nothing is reported.+defaultTestSuiteis called several times, so each process dedupes its lines.test_coverage_attribution_report_skipped, right beforeTest.cancel. A parameterized test is reported once. Below Swift 6.3 the trait cancels nothing, so it reports nothing.writeto anO_APPENDdescriptor, so a second copy of the library in the same process can't interleave with the first. Each copy opens the file from its constructor.TEST_COVERAGE_ATTRIBUTION_SKIP_FILEis set, the tests are still skipped, but nothing is reported because there is nowhere to write. Tuist writes the skip file from coverage-based selection, and it setsTEST_RUNNER_TEST_COVERAGE_ATTRIBUTION_DIRwhenever a run collects coverage evidence on macOS or the iOS simulator (TestCoverageEvidenceService.prepare). On a device the process can't write to the Mac anyway.-only-testing(a shard): only the selected classes get suites, so a listed test outside them isn't reported. It wasn't part of the run anyway.skipped.tsv.Why
Before this, the reader could only see which tests the skip list requested, not which ones were skipped. A listed test still runs if:
XCTestSuite's private-setTests:, in which case a class with only some of its tests listed silently runs all of them.DataDog's dd-sdk-swift-testing tags each test its test impact analysis skipped and tracks "forced runs" (listed tests that ran anyway). This gives Tuist the same signal: a forced run is a listed test that no process reports.
Alternatives considered
-only-testingor a crash left out. A Swift Testing test that wasn't cancelled before 6.3 shows up as passed, exactly like a test that wasn't listed. Positive evidence from the process that did the skipping is unambiguous.scope_functionsstruct, which copies of different versions read by address. A copy reading a field that an older owner doesn't have would crash. A shared append-only file avoids changing that ABI.Impact
skipped.tsvis a new contract file. Tuist's reader (CoverageObserverOutput) is not part of this PR and comes as a follow-up in tuist/tuist. Until it lands, Tuist ignores the file.test_coverage_attribution_report_skipped. No changes torecords.binorlaunches.tsv.feat/unskippable-markers) is limited to the skip section of the observer file and the README. A forced run (a listed test the report leaves out) needs nothing extra.Validation
swift testpassed, 12 tests, including the fixtures under SwiftPM, xcodebuild on macOS and on an iOS 26.3 simulator. Swift Testing cancellations are reported there.skipsTheListedTests(serial, parallel and shard),skipsTheListedSwiftTestingTests,runsEveryTestWithoutASkipListandneedsObjCToLinkTheObserverFromAStaticArchivepassed. The report has no Swift Testing lines, and the SwiftPM run writes an emptyskipped.tsv.Mach error -308 (ipc/mig) server died, and so did a run with the base branch'sSources. The cause was another session running the sameFixtures/UITestsfixture on the same simulator, with the same bundle IDs, at the same time. Once those runs stopped overlapping, every case passed.mise run lint: clean (SwiftFormat, SwiftLint and the clang static analyzer).SkipListTestsreadsskipped.tsv(newSkips.swiftparser) for the serial, parallel and shard runs of theFixtures/UITestssimulator fixture.skipsTheListedSwiftTestingTestsasserts the SwiftPM report, and that the file exists even when nothing was cancelled.-ObjCand no report without it.#if compiler(>=6.3)split is kept.🤖 Generated with Claude Code