Skip to content

Commit ced8b73

Browse files
authored
Replace setTestFilter with makeTestFilter. (#153)
* Replace `setTestFilter` with `makeTestFilter`. `setTestFilter` is too rigid because it replaces the existing test filter and that makes composition harder than it needs to be. Let's replace it with a function that returns a test filter which can then be composed: ```swift let idFilter = makeTestFilter(matching: myTestIDs) func canHaveAPony(_ test: Test) -> Bool { ... } configuration.testFilter = { test in idFilter(test) && canHaveAPony(test) } ``` Resolves rdar://119205417.
1 parent 975eded commit ced8b73

File tree

6 files changed

+60
-37
lines changed

6 files changed

+60
-37
lines changed

Sources/Testing/Running/Configuration.swift

Lines changed: 47 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ public struct Configuration: Sendable {
118118
/// - Returns: A Boolean value representing if the test satisfied the filter.
119119
public typealias TestFilter = @Sendable (_ test: Test) -> Bool
120120

121-
/// Storage for ``testFilter``.
121+
/// Storage for ``testFilter-swift.property``.
122122
private var _testFilter: TestFilter = { !$0.isHidden }
123123

124124
/// The test filter to which tests should be filtered when run.
@@ -130,36 +130,24 @@ public struct Configuration: Sendable {
130130
// By default, the test filter should always filter out hidden tests. This
131131
// is the appropriate behavior for external clients of this SPI. If the
132132
// testing library needs to enable hidden tests in its own test targets,
133-
// it should use setTestFilter(toMatch:includeHiddenTests:) instead.
133+
// it can instead use `uncheckedTestFilter`.
134134
_testFilter = { test in
135135
!test.isHidden && newValue(test)
136136
}
137137
}
138138
}
139139

140-
/// Filter tests to run to those specified via a set of test IDs.
141-
///
142-
/// - Parameters:
143-
/// - selection: A set of test IDs to be filtered.
144-
///
145-
/// By default, all tests are run and no filter is set.
146-
public mutating func setTestFilter(toMatch selection: Set<Test.ID>) {
147-
setTestFilter(toMatch: Test.ID.Selection(testIDs: selection), includeHiddenTests: false)
148-
}
149-
150-
/// Filter tests to run to those specified by a selection of test IDs.
151-
///
152-
/// - Parameters:
153-
/// - selection: A selection of test IDs to be filtered.
154-
/// - includeHiddenTests: If false, a test annotated with the `.hidden`
155-
/// trait will not be included, even if its ID is present in `selection`.
140+
/// The test filter to which tests should be filtered when run.
156141
///
157-
/// By default, all tests are run and no filter is set.
158-
mutating func setTestFilter(toMatch selection: Test.ID.Selection, includeHiddenTests: Bool) {
159-
if includeHiddenTests {
160-
_testFilter = selection.contains
161-
} else {
162-
testFilter = selection.contains
142+
/// Unlike ``testFilter-swift.property``, this property does not impose any
143+
/// checks for hidden tests. It is used by the testing library to run hidden
144+
/// tests; other callers should always use ``testFilter-swift.property``.
145+
var uncheckedTestFilter: TestFilter {
146+
get {
147+
_testFilter
148+
}
149+
set {
150+
_testFilter = newValue
163151
}
164152
}
165153

@@ -180,3 +168,38 @@ public struct Configuration: Sendable {
180168
@_spi(ExperimentalParameterizedTesting)
181169
public var testCaseFilter: TestCaseFilter = { _, _ in true }
182170
}
171+
172+
// MARK: - Test filter factory functions
173+
174+
/// Make a test filter that filters tests to those specified by a set of test
175+
/// IDs.
176+
///
177+
/// - Parameters:
178+
/// - selection: A set of test IDs to be filtered.
179+
///
180+
/// By default, all tests are run and no filter is set.
181+
@_spi(ExperimentalTestRunning)
182+
public func makeTestFilter(matching selection: some Collection<Test.ID>) -> Configuration.TestFilter {
183+
let selection = Test.ID.Selection(testIDs: selection)
184+
return makeTestFilter(matching: selection, includeHiddenTests: false)
185+
}
186+
187+
/// Make a test filter that filters tests to those specified by a set of test
188+
/// IDs, optionally including or excluding hidden tests.
189+
///
190+
/// - Parameters:
191+
/// - selection: A selection of test IDs to be filtered.
192+
/// - includeHiddenTests: If false, a test annotated with the `.hidden`
193+
/// trait will not be included, even if its ID is present in `selection`.
194+
///
195+
/// By default, all tests are run and no filter is set.
196+
func makeTestFilter(matching selection: Test.ID.Selection, includeHiddenTests: Bool) -> Configuration.TestFilter {
197+
if includeHiddenTests {
198+
return selection.contains
199+
} else {
200+
return { test in
201+
!test.isHidden && selection.contains(test)
202+
}
203+
}
204+
}
205+

Sources/Testing/Running/XCTestScaffold.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ public enum XCTestScaffold: Sendable {
211211
var configuration = Configuration()
212212
configuration.isParallelizationEnabled = false
213213
if let testIDs {
214-
configuration.setTestFilter(toMatch: Set(testIDs))
214+
configuration.testFilter = makeTestFilter(matching: testIDs)
215215
}
216216
if let tags {
217217
// Check if the test's tags intersect the set of selected tags. If there

Tests/TestingTests/PlanTests.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ struct PlanTests {
2828

2929
let selection = Test.ID.Selection(testIDs: [innerTestType.id])
3030
var configuration = Configuration()
31-
configuration.setTestFilter(toMatch: selection, includeHiddenTests: true)
31+
configuration.uncheckedTestFilter = makeTestFilter(matching: selection, includeHiddenTests: true)
3232

3333
let plan = await Runner.Plan(tests: tests, configuration: configuration)
3434
#expect(plan.steps.contains(where: { $0.test == outerTestType }))
@@ -53,7 +53,7 @@ struct PlanTests {
5353

5454
var configuration = Configuration()
5555
let selection = Test.ID.Selection(testIDs: [innerTestType.id, outerTestType.id])
56-
configuration.setTestFilter(toMatch: selection, includeHiddenTests: true)
56+
configuration.uncheckedTestFilter = makeTestFilter(matching: selection, includeHiddenTests: true)
5757

5858
let plan = await Runner.Plan(tests: tests, configuration: configuration)
5959
let planTests = plan.steps.map(\.test)
@@ -73,7 +73,7 @@ struct PlanTests {
7373

7474
var configuration = Configuration()
7575
let selection = Test.ID.Selection(testIDs: [outerTestType.id, deeplyNestedTest.id])
76-
configuration.setTestFilter(toMatch: selection, includeHiddenTests: true)
76+
configuration.uncheckedTestFilter = makeTestFilter(matching: selection, includeHiddenTests: true)
7777

7878
let plan = await Runner.Plan(tests: tests, configuration: configuration)
7979

@@ -92,7 +92,7 @@ struct PlanTests {
9292

9393
var configuration = Configuration()
9494
let selection = Test.ID.Selection(testIDs: [testSuiteA.id])
95-
configuration.setTestFilter(toMatch: selection, includeHiddenTests: true)
95+
configuration.uncheckedTestFilter = makeTestFilter(matching: selection, includeHiddenTests: true)
9696

9797
let plan = await Runner.Plan(tests: tests, configuration: configuration)
9898
let testFuncXWithTraits = try #require(plan.steps.map(\.test).first { $0.name == "x()" })

Tests/TestingTests/Runner.Plan.SnapshotTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ struct Runner_Plan_SnapshotTests {
2222
let suite = try #require(await test(for: Runner_Plan_SnapshotFixtures.self))
2323

2424
var configuration = Configuration()
25-
configuration.setTestFilter(toMatch: .init(testIDs: [suite.id]), includeHiddenTests: true)
25+
configuration.uncheckedTestFilter = makeTestFilter(matching: .init(testIDs: [suite.id]), includeHiddenTests: true)
2626

2727
let plan = await Runner.Plan(configuration: configuration)
2828
let snapshot = Runner.Plan.Snapshot(snapshotting: plan)

Tests/TestingTests/RunnerTests.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ final class RunnerTests: XCTestCase {
251251

252252
var configuration = Configuration()
253253
let selection = Test.ID.Selection(testIDs: [testSuite.id])
254-
configuration.setTestFilter(toMatch: selection, includeHiddenTests: true)
254+
configuration.uncheckedTestFilter = makeTestFilter(matching: selection, includeHiddenTests: true)
255255

256256
let runner = await Runner(testing: [
257257
testSuite,
@@ -302,7 +302,7 @@ final class RunnerTests: XCTestCase {
302302

303303
var configuration = Configuration()
304304
let selection = Test.ID.Selection(testIDs: selectedTestIDs)
305-
configuration.setTestFilter(toMatch: selection, includeHiddenTests: true)
305+
configuration.uncheckedTestFilter = makeTestFilter(matching: selection, includeHiddenTests: true)
306306

307307
let runner = await Runner(configuration: configuration)
308308
let plan = runner.plan
@@ -326,10 +326,10 @@ final class RunnerTests: XCTestCase {
326326
]
327327

328328
var configuration1 = Configuration()
329-
configuration1.setTestFilter(toMatch: .init(testIDs: selectedTestIDs), includeHiddenTests: false)
329+
configuration1.testFilter = makeTestFilter(matching: .init(testIDs: selectedTestIDs), includeHiddenTests: false)
330330

331331
var configuration2 = Configuration()
332-
configuration2.setTestFilter(toMatch: selectedTestIDs)
332+
configuration2.testFilter = makeTestFilter(matching: selectedTestIDs)
333333

334334
for configuration in [configuration1, configuration2] {
335335
let runner = await Runner(configuration: configuration)

Tests/TestingTests/TestSupport/TestingAdditions.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ func runTest(for containingType: Any.Type, configuration: Configuration = .init(
6868
func runTestFunction(named name: String, in containingType: Any.Type, configuration: Configuration = .init()) async {
6969
var configuration = configuration
7070
let selection = Test.ID.Selection(testIDs: [Test.ID(type: containingType).child(named: name)])
71-
configuration.setTestFilter(toMatch: selection, includeHiddenTests: true)
71+
configuration.uncheckedTestFilter = makeTestFilter(matching: selection, includeHiddenTests: true)
7272

7373
let runner = await Runner(configuration: configuration)
7474
await runner.run()
@@ -92,7 +92,7 @@ extension Runner {
9292

9393
var configuration = configuration
9494
let selection = Test.ID.Selection(testIDs: [Test.ID(moduleName: moduleName, nameComponents: [testName], sourceLocation: nil)])
95-
configuration.setTestFilter(toMatch: selection, includeHiddenTests: true)
95+
configuration.uncheckedTestFilter = makeTestFilter(matching: selection, includeHiddenTests: true)
9696

9797
await self.init(configuration: configuration)
9898
}
@@ -107,7 +107,7 @@ extension Runner.Plan {
107107
init(selecting containingType: Any.Type, configuration: Configuration = .init()) async {
108108
var configuration = configuration
109109
let selection = Test.ID.Selection(testIDs: [Test.ID(type: containingType)])
110-
configuration.setTestFilter(toMatch: selection, includeHiddenTests: true)
110+
configuration.uncheckedTestFilter = makeTestFilter(matching: selection, includeHiddenTests: true)
111111

112112
await self.init(configuration: configuration)
113113
}

0 commit comments

Comments
 (0)