-
Notifications
You must be signed in to change notification settings - Fork 101
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add withKnownIssue comments to known Issues #1014
base: main
Are you sure you want to change the base?
Conversation
@swift-ci test |
### Motivation: The Comment passed to withKnownIssue() is currently only used when a known issue does not occur. When a known issue does occur, it is marked isKnown but does not contain any record of the withKnownIssue() comment, making it harder to understand why the issue was considered to be known, especially if there are multiple nested withKnownIssue() calls. ### Modifications: When an issue is marked "known" by a `withKnownIssue()` call, the recorded issue will now have multiple comments in its `comments` array: 1. The comment passed to `withKnownIssue()`, if any 2. The Issue's own comment(s) If the issue is recorded within multiple nested `withKnownIssue()` calls, only the comment of the innermost matching call is added to the Issue. ### 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.
cf99d11
to
c6cbd3d
Compare
@swift-ci test |
@stmontgomery I took a crack at putting the known-issue data into a separate stored property and converting
|
@swift-ci test |
@swift-ci test |
@swift-ci test |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not the direction I'd go with this change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not the direction I'd go with this change.
@grynspan For reference, I've pushed my initial version of this PR here: main...aroben:swift-testing:known-issue-comments-v1
In that take, I just prepended the known-issue comment to Issue.comments
and left it at that. As you saw, @stmontgomery encouraged me to pull it out into its own struct to make the difference between the Issue's comment and the known-issue comment explicit.
Maybe you two can sync up and agree on an approach here? I'm happy to do it either way.
After discussion with @grynspan and @stmontgomery I've reverted the ABI changes. Instead, we append the known issue comment (if any) to |
@swift-ci please test |
I wanted to see if the known issue comment now appears in struct TryIt {
@Test func knownIssueTest() async throws {
withKnownIssue("known issue comment") {
Issue.record("issue comment")
}
}
@Test func knownIssueTest_throws() async throws {
withKnownIssue("known issue comment") {
struct TheError: Error {}
throw TheError()
}
}
} Here's what I got: $ SWT_SF_SYMBOLS_ENABLED=no xcrun swift test --filter TryIt
Building for debugging...
[1/1] Write swift-version--1EBDF3DDE0C0C582.txt
Build complete! (0.16s)
Test Suite 'Selected tests' started at 2025-04-07 10:48:10.677.
Test Suite 'swift-testingPackageTests.xctest' started at 2025-04-07 10:48:10.678.
Test Suite 'swift-testingPackageTests.xctest' passed at 2025-04-07 10:48:10.678.
Executed 0 tests, with 0 failures (0 unexpected) in 0.000 (0.000) seconds
Test Suite 'Selected tests' passed at 2025-04-07 10:48:10.678.
Executed 0 tests, with 0 failures (0 unexpected) in 0.000 (0.001) seconds
◇ Test run started.
↳ Testing Library Version: feb96cf762e5732f8702e1dc9755fa2908bfb5ba (modified)
◇ Suite TryIt started.
◇ Test knownIssueTest_throws() started.
◇ Test knownIssueTest() started.
✘ Test knownIssueTest() recorded a known issue at EventRecorderTests.swift:660:19: Issue recorded
↳ issue comment
↳ known issue comment
✘ Test knownIssueTest() passed after 0.001 seconds with 1 known issue.
✘ Test knownIssueTest_throws() recorded a known issue at EventRecorderTests.swift:665:19: Caught error: TheError()
↳ known issue comment
↳ known issue comment
✘ Test knownIssueTest_throws() passed after 0.001 seconds with 1 known issue.
✘ Suite TryIt passed after 0.001 seconds with 2 known issues.
✘ Test run with 2 tests passed after 0.001 seconds with 2 known issues. This looks decent, but you can see that Here are some ways to handle this:
I'm leaning toward 4 (and would add a test for it of course). |
I implemented this. |
@swift-ci please test |
@@ -454,7 +454,11 @@ extension Event.HumanReadableOutputRecorder { | |||
} | |||
additionalMessages += _formattedComments(issue.comments) | |||
if let knownIssueComment = issue.knownIssueContext?.comment { | |||
additionalMessages.append(_formattedComment(knownIssueComment)) | |||
if case .errorCaught = issue.kind { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you explain why this specific case is being singled out?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pushed an updated comment, how does it look to you?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like the correct fix might be to remove the comment from _matchError()
so that nothing needs to be special-cased?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note for compatibility, we would want to clear the comments
property of Issue
in _matchError()
after calling the matcher function as there could be code out there that inspects it:
withKnownIssue {
...
} matching: { issue in
issue.comments.first?.contains("abc") ?? false
}
(Something like that.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like the correct fix might be to remove the comment from
_matchError()
so that nothing needs to be special-cased?
We certainly could, but that has a downside that I mentioned in #1014 (comment):
- Remove the known issue comment from
Issue.comments
, leaving it only inIssue.knownIssueContext
.
a. This seems right from a modeling perspective, but will in practice remove the known issue comment from Xcode's inline error annotation UI
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but I'm trying not to introduce any regressions along the way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I appreciate that :) And that's a good goal—but we also need to be mindful of creating technical debt for ourselves.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, so do you think I should take approach 2 despite the regression in Xcode and the weirdness of Issue.comments
changing after the matcher
runs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We discussed this and decided to remove the comment entirely from _matchError
. This has a slight risk of causing incompatibilities because the matcher
function will no longer see the comment there, but it's actually kind of weird that the matcher sees the comment anyway since it is always the same as the comment passed to withKnownIssue
:
@Test func knownIssueCommentPassedToIssueMatcher() throws {
struct E: Error {}
try withKnownIssue("Known Issue Comment") {
throw E()
} matching: { issue in
print("Comments passed to matcher:", issue.comments)
// prints: Comments passed to matcher: ["Known Issue Comment"]
// which seems unhelpful since we can see the comment a few lines up in the withKnownIssue call
return true
}
}```
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree we should stop including the comment passed to withKnownIssue
(if any) in the comments
of the Issue
constructed in _matchError()
.
Co-authored-by: Jonathan Grynspan <[email protected]>
@swift-ci please test |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few nitpicky formatting comments I saw as I caught up with the latest changes
/// - Returns: A formatted string representing `comments`, or `nil` if there | ||
/// are none. | ||
/// - Returns: An array of formatted messages representing `comments`, or an | ||
/// empty array if there are none. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// empty array if there are none. | |
/// empty array if there are none. |
/// - Returns: A known issue context containing information about the known | ||
/// issue, if the issue is considered "known" by this known issue scope or any | ||
/// ancestor scope, or `nil` otherwise. | ||
typealias Matcher = @Sendable (Issue) -> Issue.KnownIssueContext? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Explicitly declare issue
so that the - Parameters:
entry refers to it:
typealias Matcher = @Sendable (Issue) -> Issue.KnownIssueContext? | |
typealias Matcher = @Sendable (_ issue: Issue) -> Issue.KnownIssueContext? |
/// - Returns: A known issue context containing information about the known | ||
/// issue, if the issue is considered "known" by this known issue scope or any | ||
/// ancestor scope, or `nil` otherwise. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// - Returns: A known issue context containing information about the known | |
/// issue, if the issue is considered "known" by this known issue scope or any | |
/// ancestor scope, or `nil` otherwise. | |
/// | |
/// - Returns: A known issue context containing information about the known | |
/// issue, if the issue is considered "known" by this known issue scope or any | |
/// ancestor scope, or `nil` otherwise. |
@@ -454,7 +454,11 @@ extension Event.HumanReadableOutputRecorder { | |||
} | |||
additionalMessages += _formattedComments(issue.comments) | |||
if let knownIssueComment = issue.knownIssueContext?.comment { | |||
additionalMessages.append(_formattedComment(knownIssueComment)) | |||
if case .errorCaught = issue.kind { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree we should stop including the comment passed to withKnownIssue
(if any) in the comments
of the Issue
constructed in _matchError()
.
Add withKnownIssue comments to known Issues
Motivation:
The Comment passed to withKnownIssue() is currently only used when a known issue does not occur. When a known issue does occur, it is marked isKnown but does not contain any record of the withKnownIssue() comment, making it harder to understand why the issue was considered to be known, especially if there are multiple nested withKnownIssue() calls.
Modifications:
When an issue is marked "known" by a
withKnownIssue()
call, the recorded issue will now have a newknownIssueContext
property containing the comment passed towithKnownIssue()
(if any). This comment will be included in themessages
array of theABI.EncodedEvent
that represents the issue.If the issue is recorded within multiple nested
withKnownIssue()
calls,knownIssueContext
corresponds to the innermost matching call.Checklist: