diff --git a/Sources/Testing/Issues/Confirmation.swift b/Sources/Testing/Issues/Confirmation.swift index 5848dfb50..c3f841ca8 100644 --- a/Sources/Testing/Issues/Confirmation.swift +++ b/Sources/Testing/Issues/Confirmation.swift @@ -164,7 +164,7 @@ public func confirmation( @_spi(Experimental) public func confirmation( _ comment: Comment? = nil, - expectedCount: some Confirmation.ExpectedCount, + expectedCount: some RangeExpression & Sendable, isolation: isolated (any Actor)? = #isolation, sourceLocation: SourceLocation = #_sourceLocation, _ body: (Confirmation) async throws -> sending R @@ -200,22 +200,7 @@ public func confirmation( fatalError("Unsupported") } -@_spi(Experimental) -extension Confirmation { - /// A protocol that describes a range expression that can be used with - /// ``confirmation(_:expectedCount:isolation:sourceLocation:_:)-9rt6m``. - /// - /// This protocol represents any expression that describes a range of - /// confirmation counts. For example, the expression `1 ..< 10` automatically - /// conforms to it. - /// - /// You do not generally need to add conformances to this type yourself. It is - /// used by the testing library to abstract away the different range types - /// provided by the Swift standard library. - public protocol ExpectedCount: Sendable, RangeExpression {} -} - -extension Confirmation.ExpectedCount { +extension RangeExpression where Bound == Int, Self: Sendable { /// Get an instance of ``Issue/Kind-swift.enum`` corresponding to this value. /// /// - Parameters: @@ -233,18 +218,3 @@ extension Confirmation.ExpectedCount { } } } - -@_spi(Experimental) -extension ClosedRange: Confirmation.ExpectedCount {} - -@_spi(Experimental) -extension PartialRangeFrom: Confirmation.ExpectedCount {} - -@_spi(Experimental) -extension PartialRangeThrough: Confirmation.ExpectedCount {} - -@_spi(Experimental) -extension PartialRangeUpTo: Confirmation.ExpectedCount {} - -@_spi(Experimental) -extension Range: Confirmation.ExpectedCount {} diff --git a/Sources/Testing/Issues/Issue.swift b/Sources/Testing/Issues/Issue.swift index 91602ef7c..3ad035114 100644 --- a/Sources/Testing/Issues/Issue.swift +++ b/Sources/Testing/Issues/Issue.swift @@ -52,7 +52,7 @@ public struct Issue: Sendable { /// the confirmation passed to these functions' `body` closures is confirmed /// too few or too many times. @_spi(Experimental) - indirect case confirmationOutOfRange(actual: Int, expected: any Confirmation.ExpectedCount) + indirect case confirmationOutOfRange(actual: Int, expected: any RangeExpression & Sendable) /// An issue due to an `Error` being thrown by a test function and caught by /// the testing library. @@ -227,8 +227,14 @@ extension Issue { /// /// - Parameter issue: The original issue that gets snapshotted. public init(snapshotting issue: borrowing Issue) { - self.kind = Issue.Kind.Snapshot(snapshotting: issue.kind) - self.comments = issue.comments + if case .confirmationOutOfRange = issue.kind { + // Work around poor stringification of this issue kind in Xcode 16. + self.kind = .unconditional + self.comments = CollectionOfOne("\(issue.kind)") + issue.comments + } else { + self.kind = Issue.Kind.Snapshot(snapshotting: issue.kind) + self.comments = issue.comments + } self.sourceContext = issue.sourceContext self.isKnown = issue.isKnown } diff --git a/Tests/TestingTests/ConfirmationTests.swift b/Tests/TestingTests/ConfirmationTests.swift index 11d04b48c..7c2dca474 100644 --- a/Tests/TestingTests/ConfirmationTests.swift +++ b/Tests/TestingTests/ConfirmationTests.swift @@ -116,16 +116,28 @@ struct UnsuccessfulConfirmationTests { } @Test(.hidden, arguments: [ - 1 ... 2 as any Confirmation.ExpectedCount, + 1 ... 2 as any ExpectedCount, 1 ..< 2, 1 ..< 3, ..<2, ...2, 999..., ]) - func confirmedOutOfRange(_ range: any Confirmation.ExpectedCount) async { + func confirmedOutOfRange(_ range: any ExpectedCount) async { await confirmation(expectedCount: range) { (thingHappened) async in thingHappened(count: 3) } } } + +// MARK: - + +/// Needed since we don't have generic test functions, so we need a concrete +/// argument type for `confirmedOutOfRange(_:)`, but we can't write +/// `any RangeExpression & Sendable`. ([96960993](rdar://96960993)) +protocol ExpectedCount: RangeExpression, Sendable where Bound == Int {} +extension ClosedRange: ExpectedCount {} +extension PartialRangeFrom: ExpectedCount {} +extension PartialRangeThrough: ExpectedCount {} +extension PartialRangeUpTo: ExpectedCount {} +extension Range: ExpectedCount {}