@@ -171,6 +171,60 @@ extension Runner {
171
171
}
172
172
}
173
173
174
+ /// Post `testStarted` and `testEnded` (or `testSkipped`) events for the test
175
+ /// at the given plan step.
176
+ ///
177
+ /// - Parameters:
178
+ /// - step: The plan step for which events should be posted.
179
+ /// - configuration: The configuration to use for running.
180
+ /// - body: A function to execute between the started/ended events.
181
+ ///
182
+ /// - Throws: Whatever is thrown by `body` or while handling any issues
183
+ /// recorded in the process.
184
+ ///
185
+ /// - Returns: Whatever is returned by `body`.
186
+ ///
187
+ /// This function does _not_ post the `planStepStarted` and `planStepEnded`
188
+ /// events.
189
+ private static func _postingTestStartedAndEndedEvents< R> ( for step: Plan . Step , configuration: Configuration , _ body: @Sendable ( ) async throws -> R ) async throws -> R {
190
+ // Whether to send a `.testEnded` event at the end of running this step.
191
+ // Some steps' actions may not require a final event to be sent — for
192
+ // example, a skip event only sends `.testSkipped`.
193
+ let shouldSendTestEnded : Bool
194
+
195
+ // Determine what kind of event to send for this step based on its action.
196
+ switch step. action {
197
+ case . run:
198
+ Event . post ( . testStarted, for: ( step. test, nil ) , configuration: configuration)
199
+ shouldSendTestEnded = true
200
+ case let . skip( skipInfo) :
201
+ Event . post ( . testSkipped( skipInfo) , for: ( step. test, nil ) , configuration: configuration)
202
+ shouldSendTestEnded = false
203
+ case let . recordIssue( issue) :
204
+ // Scope posting the issue recorded event such that issue handling
205
+ // traits have the opportunity to handle it. This ensures that if a test
206
+ // has an issue handling trait _and_ some other trait which caused an
207
+ // issue to be recorded, the issue handling trait can process the issue
208
+ // even though it wasn't recorded by the test function.
209
+ try await Test . withCurrent ( step. test) {
210
+ try await _applyIssueHandlingTraits ( for: step. test) {
211
+ // Don't specify `configuration` when posting this issue so that
212
+ // traits can provide scope and potentially customize the
213
+ // configuration.
214
+ Event . post ( . issueRecorded( issue) , for: ( step. test, nil ) )
215
+ }
216
+ }
217
+ shouldSendTestEnded = false
218
+ }
219
+ defer {
220
+ if shouldSendTestEnded {
221
+ Event . post ( . testEnded, for: ( step. test, nil ) , configuration: configuration)
222
+ }
223
+ }
224
+
225
+ return try await body ( )
226
+ }
227
+
174
228
/// Run this test.
175
229
///
176
230
/// - Parameters:
@@ -193,64 +247,34 @@ extension Runner {
193
247
// Exit early if the task has already been cancelled.
194
248
try Task . checkCancellation ( )
195
249
196
- // Whether to send a `.testEnded` event at the end of running this step.
197
- // Some steps' actions may not require a final event to be sent — for
198
- // example, a skip event only sends `.testSkipped`.
199
- let shouldSendTestEnded : Bool
200
-
201
- let configuration = _configuration
202
-
203
- // Determine what action to take for this step.
204
250
if let step = stepGraph. value {
251
+ let configuration = _configuration
205
252
Event . post ( . planStepStarted( step) , for: ( step. test, nil ) , configuration: configuration)
206
-
207
- // Determine what kind of event to send for this step based on its action.
208
- switch step. action {
209
- case . run:
210
- Event . post ( . testStarted, for: ( step. test, nil ) , configuration: configuration)
211
- shouldSendTestEnded = true
212
- case let . skip( skipInfo) :
213
- Event . post ( . testSkipped( skipInfo) , for: ( step. test, nil ) , configuration: configuration)
214
- shouldSendTestEnded = false
215
- case let . recordIssue( issue) :
216
- // Scope posting the issue recorded event such that issue handling
217
- // traits have the opportunity to handle it. This ensures that if a test
218
- // has an issue handling trait _and_ some other trait which caused an
219
- // issue to be recorded, the issue handling trait can process the issue
220
- // even though it wasn't recorded by the test function.
221
- try await Test . withCurrent ( step. test) {
222
- try await _applyIssueHandlingTraits ( for: step. test) {
223
- // Don't specify `configuration` when posting this issue so that
224
- // traits can provide scope and potentially customize the
225
- // configuration.
226
- Event . post ( . issueRecorded( issue) , for: ( step. test, nil ) )
227
- }
228
- }
229
- shouldSendTestEnded = false
230
- }
231
- } else {
232
- shouldSendTestEnded = false
233
- }
234
- defer {
235
- if let step = stepGraph. value {
236
- if shouldSendTestEnded {
237
- Event . post ( . testEnded, for: ( step. test, nil ) , configuration: configuration)
238
- }
253
+ defer {
239
254
Event . post ( . planStepEnded( step) , for: ( step. test, nil ) , configuration: configuration)
240
255
}
241
- }
242
256
243
- if let step = stepGraph. value, case . run = step. action {
244
257
await Test . withCurrent ( step. test) {
245
258
_ = await Issue . withErrorRecording ( at: step. test. sourceLocation, configuration: configuration) {
246
- try await _applyScopingTraits ( for: step. test, testCase: nil ) {
247
- // Run the test function at this step (if one is present.)
248
- if let testCases = step. test. testCases {
249
- try await _runTestCases ( testCases, within: step)
259
+ switch step. action {
260
+ case . run:
261
+ try await _applyScopingTraits ( for: step. test, testCase: nil ) {
262
+ try await _postingTestStartedAndEndedEvents ( for: step, configuration: configuration) {
263
+ // Run the test function at this step (if one is present.)
264
+ if let testCases = step. test. testCases {
265
+ try await _runTestCases ( testCases, within: step)
266
+ }
267
+
268
+ // Run the children of this test (i.e. the tests in this suite.)
269
+ try await _runChildren ( of: stepGraph)
270
+ }
271
+ }
272
+ default :
273
+ // Skipping this step or otherwise not running it. Post appropriate
274
+ // started/ended events for the test and walk any child nodes.
275
+ try await _postingTestStartedAndEndedEvents ( for: step, configuration: configuration) {
276
+ try await _runChildren ( of: stepGraph)
250
277
}
251
-
252
- // Run the children of this test (i.e. the tests in this suite.)
253
- try await _runChildren ( of: stepGraph)
254
278
}
255
279
}
256
280
}
0 commit comments