Skip to content

Commit 1d60944

Browse files
authored
Ignore ExpectationFailedError when thrown by the body closure passed to withKnownIssue (#1441)
This fixes an issue where a redundant, second known issue is recorded when `try #require()` fails within the body closure of `withKnownIssue`. For example, in the following example code: ```swift @test func example() { withKnownIssue { try #require(Bool(false)) } } ``` two (known) issues are recorded: > ✘ Test example() recorded a known issue at KnownIssueTests.swift:641:9: Expectation failed: Bool(false) > ✘ Test example() recorded a known issue at KnownIssueTests.swift:640:18: An API was misused > ↳ Recorded an error of type ExpectationFailedError representing an expectation that failed and was already recorded: ... Of these, only the first should be recorded and the second should be suppressed. Fixes rdar://153550847 ### Motivation: It should be possible to use `try #require()` in the body closure passed to `withKnownIssue`, and _matching_ failures should only cause a single known issue to be recorded. The second issue shown above describes an infrastructural `Error`-conforming type which is not generally intended to be included in the results test authors see, and can cause confusion. ### Modifications: - When attempting to match an error thrown by a `withKnownIssue` body closure, ignore the error if it's of type `ExpectationFailedError. - Add a new unit test validating this, which fails prior to the fix. ### Checklist: - [x] Code and documentation should follow the style of the [Style Guide](https://github.com/apple/swift-testing/blob/main/Documentation/StyleGuide.md). - [x] If public symbols are renamed or modified, DocC references should be updated.
1 parent 00c0b1b commit 1d60944

File tree

2 files changed

+27
-0
lines changed

2 files changed

+27
-0
lines changed

Sources/Testing/Issues/KnownIssue.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,13 @@ struct KnownIssueScope: Sendable {
7777
/// - sourceLocation: The source location to which the issue should be
7878
/// attributed.
7979
private func _matchError(_ error: any Error, in scope: KnownIssueScope, comment: Comment?, sourceLocation: SourceLocation) throws {
80+
// ExpectationFailedError is thrown by expectation checking functions to
81+
// indicate a condition evaluated to `false`. Those functions record their
82+
// own issue, so we don't need to create a new issue and attempt to match it.
83+
if error is ExpectationFailedError {
84+
return
85+
}
86+
8087
let sourceContext = SourceContext(backtrace: Backtrace(forFirstThrowOf: error), sourceLocation: sourceLocation)
8188
var issue = Issue(kind: .errorCaught(error), comments: [], sourceContext: sourceContext)
8289
if let context = scope.matcher(issue) {

Tests/TestingTests/KnownIssueTests.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,26 @@ final class KnownIssueTests: XCTestCase {
574574
await fulfillment(of: [issueRecorded, knownIssueNotRecorded], timeout: 0.0)
575575
}
576576

577+
func testKnownIssueWithRequiredExpectationFailure() async {
578+
let issueRecorded = expectation(description: "Issue recorded")
579+
580+
var configuration = Configuration()
581+
configuration.eventHandler = { event, _ in
582+
guard case .issueRecorded = event.kind else {
583+
return
584+
}
585+
issueRecorded.fulfill()
586+
}
587+
588+
await Test {
589+
withKnownIssue {
590+
try #require(Bool(false))
591+
}
592+
}.run(configuration: configuration)
593+
594+
await fulfillment(of: [issueRecorded], timeout: 0.0)
595+
}
596+
577597
func testAsyncKnownIssueThatDoesNotAlwaysOccur() async {
578598
struct MyError: Error {}
579599

0 commit comments

Comments
 (0)