From 3cf0e5531ca7b77d827ca9cc18bc5007fd3d4e21 Mon Sep 17 00:00:00 2001 From: Brandon Williams Date: Thu, 1 May 2025 10:02:56 -0500 Subject: [PATCH 1/3] Allow overriding file/line/column of where issues are reported. --- Sources/IssueReporting/ReportIssue.swift | 31 +++++++++++++++++++ .../SwiftTestingTests.swift | 14 +++++++++ Tests/IssueReportingTests/XCTestTests.swift | 12 +++++++ 3 files changed, 57 insertions(+) diff --git a/Sources/IssueReporting/ReportIssue.swift b/Sources/IssueReporting/ReportIssue.swift index 3a2af15..99c9cac 100644 --- a/Sources/IssueReporting/ReportIssue.swift +++ b/Sources/IssueReporting/ReportIssue.swift @@ -1,3 +1,22 @@ +public struct ReportIssueContext: Sendable { + public let column: UInt + public let fileID: StaticString + public let filePath: StaticString + public let line: UInt + public init( + fileID: StaticString = #fileID, + filePath: StaticString = #filePath, + line: UInt = #line, + column: UInt = #column + ) { + self.column = column + self.fileID = fileID + self.filePath = filePath + self.line = line + } +} +@TaskLocal public var reportIssueContext: ReportIssueContext? + /// Report an issue. /// /// Invoking this function has two different behaviors depending on the context: @@ -34,6 +53,12 @@ public func reportIssue( line: UInt = #line, column: UInt = #column ) { + let (fileID, filePath, line, column) = ( + reportIssueContext?.fileID ?? fileID, + reportIssueContext?.filePath ?? filePath, + reportIssueContext?.line ?? line, + reportIssueContext?.column ?? column + ) guard let context = TestContext.current else { guard !isTesting else { return } if let observer = FailureObserver.current { @@ -101,6 +126,12 @@ public func reportIssue( line: UInt = #line, column: UInt = #column ) { + let (fileID, filePath, line, column) = ( + reportIssueContext?.fileID ?? fileID, + reportIssueContext?.filePath ?? filePath, + reportIssueContext?.line ?? line, + reportIssueContext?.column ?? column + ) guard let context = TestContext.current else { guard !isTesting else { return } if let observer = FailureObserver.current { diff --git a/Tests/IssueReportingTests/SwiftTestingTests.swift b/Tests/IssueReportingTests/SwiftTestingTests.swift index fef8993..601da80 100644 --- a/Tests/IssueReportingTests/SwiftTestingTests.swift +++ b/Tests/IssueReportingTests/SwiftTestingTests.swift @@ -117,6 +117,20 @@ await Task.yield() } } + + @Test func overrideReportIssueContext() { + withKnownIssue { + $reportIssueContext.withValue(ReportIssueContext()) { + reportIssue("Something went wrong") + } + } matching: { issue in + let expectedReportingLine = #line - 4 + print("issue.sourceLocation?.line", issue.sourceLocation?.line) + print("expectedReportingLine", expectedReportingLine) + return issue.sourceLocation?.line == expectedReportingLine + && issue.description == "Issue recorded: Something went wrong" + } + } } private struct Failure: Error {} diff --git a/Tests/IssueReportingTests/XCTestTests.swift b/Tests/IssueReportingTests/XCTestTests.swift index d5219a8..78934d5 100644 --- a/Tests/IssueReportingTests/XCTestTests.swift +++ b/Tests/IssueReportingTests/XCTestTests.swift @@ -49,6 +49,18 @@ final class XCTestTests: XCTestCase { func testWithExpectedIssue_Throwing() { withExpectedIssue { throw Failure() } } + + func testOverrideReportIssueContext() { + XCTExpectFailure { + $reportIssueContext.withValue(ReportIssueContext()) { + reportIssue("Something went wrong") + } + } issueMatcher: { issue in + let expectedReportingLine = #line - 4 + return issue.sourceCodeContext.location?.lineNumber == expectedReportingLine + && issue.compactDescription == "failed - Something went wrong" + } + } #endif } From 061e4eb3dbbc28b6813abac7fcb10d2b3293c389 Mon Sep 17 00:00:00 2001 From: Brandon Williams Date: Thu, 1 May 2025 12:06:12 -0500 Subject: [PATCH 2/3] wip --- Sources/IssueReporting/ReportIssue.swift | 91 ++++++++++-------------- 1 file changed, 36 insertions(+), 55 deletions(-) diff --git a/Sources/IssueReporting/ReportIssue.swift b/Sources/IssueReporting/ReportIssue.swift index 99c9cac..b7160d9 100644 --- a/Sources/IssueReporting/ReportIssue.swift +++ b/Sources/IssueReporting/ReportIssue.swift @@ -1,22 +1,3 @@ -public struct ReportIssueContext: Sendable { - public let column: UInt - public let fileID: StaticString - public let filePath: StaticString - public let line: UInt - public init( - fileID: StaticString = #fileID, - filePath: StaticString = #filePath, - line: UInt = #line, - column: UInt = #column - ) { - self.column = column - self.fileID = fileID - self.filePath = filePath - self.line = line - } -} -@TaskLocal public var reportIssueContext: ReportIssueContext? - /// Report an issue. /// /// Invoking this function has two different behaviors depending on the context: @@ -54,10 +35,10 @@ public func reportIssue( column: UInt = #column ) { let (fileID, filePath, line, column) = ( - reportIssueContext?.fileID ?? fileID, - reportIssueContext?.filePath ?? filePath, - reportIssueContext?.line ?? line, - reportIssueContext?.column ?? column + IssueContext.current?.fileID ?? fileID, + IssueContext.current?.filePath ?? filePath, + IssueContext.current?.line ?? line, + IssueContext.current?.column ?? column ) guard let context = TestContext.current else { guard !isTesting else { return } @@ -66,20 +47,20 @@ public func reportIssue( for reporter in IssueReporters.current { reporter.expectIssue( message(), - fileID: IssueContext.current?.fileID ?? fileID, - filePath: IssueContext.current?.filePath ?? filePath, - line: IssueContext.current?.line ?? line, - column: IssueContext.current?.column ?? column + fileID: fileID, + filePath: filePath, + line: line, + column: column ) } } else { for reporter in IssueReporters.current { reporter.reportIssue( message(), - fileID: IssueContext.current?.fileID ?? fileID, - filePath: IssueContext.current?.filePath ?? filePath, - line: IssueContext.current?.line ?? line, - column: IssueContext.current?.column ?? column + fileID: fileID, + filePath: filePath, + line: line, + column: column ) } } @@ -90,16 +71,16 @@ public func reportIssue( case .swiftTesting: _recordIssue( message: message(), - fileID: "\(IssueContext.current?.fileID ?? fileID)", - filePath: "\(IssueContext.current?.filePath ?? filePath)", - line: Int(IssueContext.current?.line ?? line), - column: Int(IssueContext.current?.column ?? column) + fileID: "\(fileID)", + filePath: "\(filePath)", + line: Int(line), + column: Int(column) ) case .xcTest: _XCTFail( message().withAppHostWarningIfNeeded() ?? "", - file: IssueContext.current?.filePath ?? filePath, - line: IssueContext.current?.line ?? line + file: filePath, + line: line ) @unknown default: break } @@ -127,10 +108,10 @@ public func reportIssue( column: UInt = #column ) { let (fileID, filePath, line, column) = ( - reportIssueContext?.fileID ?? fileID, - reportIssueContext?.filePath ?? filePath, - reportIssueContext?.line ?? line, - reportIssueContext?.column ?? column + IssueContext.current?.fileID ?? fileID, + IssueContext.current?.filePath ?? filePath, + IssueContext.current?.line ?? line, + IssueContext.current?.column ?? column ) guard let context = TestContext.current else { guard !isTesting else { return } @@ -140,10 +121,10 @@ public func reportIssue( reporter.expectIssue( error, message(), - fileID: IssueContext.current?.fileID ?? fileID, - filePath: IssueContext.current?.filePath ?? filePath, - line: IssueContext.current?.line ?? line, - column: IssueContext.current?.column ?? column + fileID: fileID, + filePath: filePath, + line: line, + column: column ) } } else { @@ -151,10 +132,10 @@ public func reportIssue( reporter.reportIssue( error, message(), - fileID: IssueContext.current?.fileID ?? fileID, - filePath: IssueContext.current?.filePath ?? filePath, - line: IssueContext.current?.line ?? line, - column: IssueContext.current?.column ?? column + fileID: fileID, + filePath: filePath, + line: line, + column: column ) } } @@ -166,16 +147,16 @@ public func reportIssue( _recordError( error: error, message: message(), - fileID: "\(IssueContext.current?.fileID ?? fileID)", - filePath: "\(IssueContext.current?.filePath ?? filePath)", - line: Int(IssueContext.current?.line ?? line), - column: Int(IssueContext.current?.column ?? column) + fileID: "\(fileID)", + filePath: "\(filePath)", + line: Int(line), + column: Int(column) ) case .xcTest: _XCTFail( "Caught error: \(error)\(message().map { ": \($0)" } ?? "")".withAppHostWarningIfNeeded(), - file: IssueContext.current?.filePath ?? filePath, - line: IssueContext.current?.line ?? line + file: filePath, + line: line ) @unknown default: break } From 1d686c9c0295a8a7ade48f5b815b03679ae991a2 Mon Sep 17 00:00:00 2001 From: Brandon Williams Date: Thu, 1 May 2025 12:08:18 -0500 Subject: [PATCH 3/3] wip --- Tests/IssueReportingTests/SwiftTestingTests.swift | 6 ++---- Tests/IssueReportingTests/XCTestTests.swift | 4 ++-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/Tests/IssueReportingTests/SwiftTestingTests.swift b/Tests/IssueReportingTests/SwiftTestingTests.swift index 601da80..3969ac6 100644 --- a/Tests/IssueReportingTests/SwiftTestingTests.swift +++ b/Tests/IssueReportingTests/SwiftTestingTests.swift @@ -118,15 +118,13 @@ } } - @Test func overrideReportIssueContext() { + @Test func overrideIssueContext() { withKnownIssue { - $reportIssueContext.withValue(ReportIssueContext()) { + withIssueContext(fileID: #fileID, filePath: #filePath, line: #line, column: #column) { reportIssue("Something went wrong") } } matching: { issue in let expectedReportingLine = #line - 4 - print("issue.sourceLocation?.line", issue.sourceLocation?.line) - print("expectedReportingLine", expectedReportingLine) return issue.sourceLocation?.line == expectedReportingLine && issue.description == "Issue recorded: Something went wrong" } diff --git a/Tests/IssueReportingTests/XCTestTests.swift b/Tests/IssueReportingTests/XCTestTests.swift index 78934d5..22d55c3 100644 --- a/Tests/IssueReportingTests/XCTestTests.swift +++ b/Tests/IssueReportingTests/XCTestTests.swift @@ -50,9 +50,9 @@ final class XCTestTests: XCTestCase { withExpectedIssue { throw Failure() } } - func testOverrideReportIssueContext() { + func testOverrideIssueContext() { XCTExpectFailure { - $reportIssueContext.withValue(ReportIssueContext()) { + withIssueContext(fileID: #fileID, filePath: #filePath, line: #line, column: #column) { reportIssue("Something went wrong") } } issueMatcher: { issue in