@@ -171,6 +171,60 @@ extension Runner {
171171 }
172172 }
173173
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+
174228 /// Run this test.
175229 ///
176230 /// - Parameters:
@@ -193,64 +247,34 @@ extension Runner {
193247 // Exit early if the task has already been cancelled.
194248 try Task . checkCancellation ( )
195249
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.
204250 if let step = stepGraph. value {
251+ let configuration = _configuration
205252 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 {
239254 Event . post ( . planStepEnded( step) , for: ( step. test, nil ) , configuration: configuration)
240255 }
241- }
242256
243- if let step = stepGraph. value, case . run = step. action {
244257 await Test . withCurrent ( step. test) {
245258 _ = 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)
250277 }
251-
252- // Run the children of this test (i.e. the tests in this suite.)
253- try await _runChildren ( of: stepGraph)
254278 }
255279 }
256280 }
0 commit comments