From a7ea40f1e51d8a896bc2ec85a06516e031b2fb27 Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Thu, 25 Apr 2024 11:57:00 -0400 Subject: [PATCH] Split `.bug()` into two taking a URL or a number. This PR changes the initializers for `.bug()` from ones taking an undecorated and unspecified "identifier" to ones taking either a URL (as a string) or a numeric ID ("bug number.") The existing interface is ambiguous to tools authors seeking to integrate with it. They must treat _every_ bug as potentially containing a URL with fallback paths if a bug's ID cannot be parsed as a URL. By splitting URLs and numbers up into two separate properties, tools authors can provide reliable, distinct interfaces for bugs known by number vs. those known by URL. --- .../Testing/Testing.docc/AssociatingBugs.md | 48 +++++--- .../Testing/Testing.docc/BugIdentifiers.md | 63 +++++----- .../Testing.docc/EnablingAndDisabling.md | 14 ++- Sources/Testing/Testing.docc/Traits.md | 5 +- Sources/Testing/Testing.docc/Traits/Trait.md | 5 +- Sources/Testing/Traits/Bug.swift | 115 +++++++----------- Sources/Testing/Traits/Comment.swift | 6 +- .../DiagnosticMessage+Diagnosing.swift | 26 +--- .../Support/DiagnosticMessage.swift | 2 +- .../TestDeclarationMacroTests.swift | 18 +-- Tests/TestingTests/EventRecorderTests.swift | 1 - Tests/TestingTests/Test.SnapshotTests.swift | 2 +- Tests/TestingTests/Traits/BugTests.swift | 62 ++++++---- 13 files changed, 182 insertions(+), 185 deletions(-) diff --git a/Sources/Testing/Testing.docc/AssociatingBugs.md b/Sources/Testing/Testing.docc/AssociatingBugs.md index a1b722383..2cb632b1e 100644 --- a/Sources/Testing/Testing.docc/AssociatingBugs.md +++ b/Sources/Testing/Testing.docc/AssociatingBugs.md @@ -25,12 +25,32 @@ specific bugs with tests that reproduce them or verify they are fixed. ## Associate a bug with a test -To associate a bug with a test, use the ``Trait/bug(_:_:)-2u8j9`` or -``Trait/bug(_:_:)-7mo2w`` function. The first argument to this function is the -bug's _identifier_ in its bug-tracking system: +To associate a bug with a test, use one of these functions: +- ``Trait/bug(_:_:)`` +- ``Trait/bug(_:id:_:)-10yf5`` +- ``Trait/bug(_:id:_:)-3vtpl`` + +The first argument to these functions is a URL representing the bug in its +bug-tracking system: + +```swift +@Test("Food truck engine works", .bug("https://www.example.com/issues/12345")) +func engineWorks() async { + var foodTruck = FoodTruck() + await foodTruck.engine.start() + #expect(foodTruck.engine.isRunning) +} +``` + +You can also specify the bug's _unique identifier_ in its bug-tracking system in +addition to, or instead of, its URL: ```swift -@Test("Food truck engine works", .bug("12345"), .bug(67890)) +@Test( + "Food truck engine works", + .bug(id: "12345"), + .bug("https://www.example.com/issues/67890", id: 67890) +) func engineWorks() async { var foodTruck = FoodTruck() await foodTruck.engine.start() @@ -38,22 +58,22 @@ func engineWorks() async { } ``` -The bug identifier can be specified as an integer or as a string; if it is -specified as a string, it must be parseable as an unsigned integer or as a URL. -For more information on the formats recognized by the testing library, see -. +A bug's URL is passed as a string and must be parseable according to +[RFC 3986](https://www.ietf.org/rfc/rfc3986.txt). A bug's unique identifier +can be passed as an integer or as a string. For more information on the formats +recognized by the testing library, see . -## Add comments to associated bugs +## Add titles to associated bugs -A bug identifier may be insufficient to uniquely and clearly identify a bug -associated with a test. Bug trackers universally provide a "title" field for -bugs that is not visible to the testing library. To add a bug's title to a test, -include it after the bug's identifier: +A bug's unique identifier or URL may be insufficient to uniquely and clearly +identify a bug associated with a test. Bug trackers universally provide a +"title" field for bugs that is not visible to the testing library. To add a +bug's title to a test, include it after the bug's unique identifier or URL: ```swift @Test( "Food truck has napkins", - .bug("12345", "Forgot to buy more napkins") + .bug(id: "12345", "Forgot to buy more napkins") ) func hasNapkins() async { ... diff --git a/Sources/Testing/Testing.docc/BugIdentifiers.md b/Sources/Testing/Testing.docc/BugIdentifiers.md index c41cc491d..91d5b83e9 100644 --- a/Sources/Testing/Testing.docc/BugIdentifiers.md +++ b/Sources/Testing/Testing.docc/BugIdentifiers.md @@ -14,46 +14,41 @@ Examine how the testing library interprets bug identifiers provided by developer ## Overview -As a convenience, the testing library assumes that bug identifiers with specific -formats are associated with some common bug-tracking systems. +The testing library supports two distinct ways to identify a bug: + +1. A URL linking to more information about the bug; and +2. A unique identifier in the bug's associated bug-tracking system. - Note: "Bugs" as described in this document may also be referred to as - "issues." To avoid confusion with the ``Issue`` type in the testing library, - this document consistently refers to them as "bugs." - -### Recognized formats - -- If the bug identifier can be parsed as a URL according to - [RFC 3986](https://www.ietf.org/rfc/rfc3986.txt), it is assumed to represent - an issue tracked at that URL. -- If the bug identifier begins with `"FB"` and the rest of it can be parsed as - an unsigned integer, it's assumed to represent a bug filed with the - [Apple Feedback Assistant](https://feedbackassistant.apple.com). -- If the bug identifier can be parsed as an unsigned integer, it's assumed to - represent an issue with that numeric identifier in an unspecified bug-tracking - system. -- All other bug identifiers are considered invalid and will cause the compiler - to generate an error at compile time. +"issues." To avoid confusion with the ``Issue`` type in the testing library, +this document consistently refers to them as "bugs." - +To create an instance of ``Bug`` with a URL, use the ``Trait/bug(_:_:)`` trait. +At compile time, the testing library will validate that the given string can be +parsed as a URL according to [RFC 3986](https://www.ietf.org/rfc/rfc3986.txt). + +To create an instance of ``Bug`` with a bug's unique identifier, use the +``Trait/bug(_:id:_:)-10yf5`` trait. The testing library does not require that a +bug's unique identifier match any particular format, but will interpret unique +identifiers starting with `"FB"` as referring to bugs tracked with the +[Apple Feedback Assistant](https://feedbackassistant.apple.com). For +convenience, you can also directly pass an integer as a bug's identifier using +``Trait/bug(_:id:_:)-3vtpl``. ### Examples -| Trait function | Valid | Inferred bug-tracking system | -|-|:-:|-| -| `.bug(12345)` | Yes | None | -| `.bug("12345")` | Yes | None | -| `.bug("Things don't work")` | **No** | None | -| `.bug("https://github.com/apple/swift/pull/12345")` | Yes | [GitHub Issues for the Swift project](https://github.com/apple/swift/issues) | -| `.bug("https://bugs.webkit.org/show_bug.cgi?id=12345")` | Yes | [WebKit Bugzilla](https://bugs.webkit.org/) | -| `.bug("FB12345")` | Yes | Apple Feedback Assistant | +| Trait Function | Inferred Bug-Tracking System | +|-|-| +| `.bug(id: 12345)` | None | +| `.bug(id: "12345")` | None | +| `.bug("https://www.example.com?id=12345", id: "12345")` | None | +| `.bug("https://github.com/apple/swift/pull/12345")` | [GitHub Issues for the Swift project](https://github.com/apple/swift/issues) | +| `.bug("https://bugs.webkit.org/show_bug.cgi?id=12345")` | [WebKit Bugzilla](https://bugs.webkit.org/) | +| `.bug(id: "FB12345")` | Apple Feedback Assistant | diff --git a/Sources/Testing/Testing.docc/EnablingAndDisabling.md b/Sources/Testing/Testing.docc/EnablingAndDisabling.md index 027fd9da2..fdf28c65b 100644 --- a/Sources/Testing/Testing.docc/EnablingAndDisabling.md +++ b/Sources/Testing/Testing.docc/EnablingAndDisabling.md @@ -82,8 +82,14 @@ func isCold() async throws { ... } ``` If a test is disabled because of a problem for which there is a corresponding -bug report, you can use the ``Trait/bug(_:_:)-2u8j9`` or -``Trait/bug(_:_:)-7mo2w`` function to show the relationship: +bug report, you can use one of these functions to show the relationship +between the test and the bug report: + +- ``Trait/bug(_:_:)`` +- ``Trait/bug(_:id:_:)-10yf5`` +- ``Trait/bug(_:id:_:)-3vtpl`` + +For example, the following test cannot run due to bug number `"12345"`: ```swift @Test( @@ -96,8 +102,8 @@ func isCold() async throws { ... } ``` If a test has multiple conditions applied to it, they must _all_ pass for it to -run. Otherwise, the test notes the first condition to fail as the reason the test -is skipped. +run. Otherwise, the test notes the first condition to fail as the reason the +test is skipped. ### Handle complex conditions diff --git a/Sources/Testing/Testing.docc/Traits.md b/Sources/Testing/Testing.docc/Traits.md index 90bc6ad25..50b847e29 100644 --- a/Sources/Testing/Testing.docc/Traits.md +++ b/Sources/Testing/Testing.docc/Traits.md @@ -46,8 +46,9 @@ HIDDEN: .serialized is experimental SPI pending feature review. - - - ``Tag()`` -- ``Trait/bug(_:_:)-2u8j9`` -- ``Trait/bug(_:_:)-7mo2w`` +- ``Trait/bug(_:_:)`` +- ``Trait/bug(_:id:_:)-10yf5`` +- ``Trait/bug(_:id:_:)-3vtpl`` ### Creating custom traits diff --git a/Sources/Testing/Testing.docc/Traits/Trait.md b/Sources/Testing/Testing.docc/Traits/Trait.md index 8c28dd197..3435a8471 100644 --- a/Sources/Testing/Testing.docc/Traits/Trait.md +++ b/Sources/Testing/Testing.docc/Traits/Trait.md @@ -30,8 +30,9 @@ See https://swift.org/CONTRIBUTORS.txt for Swift project authors ### Associating bugs -- ``Trait/bug(_:_:)-2u8j9`` -- ``Trait/bug(_:_:)-7mo2w`` +- ``Trait/bug(_:_:)`` +- ``Trait/bug(_:id:_:)-10yf5`` +- ``Trait/bug(_:id:_:)-3vtpl`` ### Adding information to tests - ``Trait/comments`` diff --git a/Sources/Testing/Traits/Bug.swift b/Sources/Testing/Traits/Bug.swift index 51a0d0566..48a718dfa 100644 --- a/Sources/Testing/Traits/Bug.swift +++ b/Sources/Testing/Traits/Bug.swift @@ -12,84 +12,49 @@ /// /// To add this trait to a test, use one of the following functions: /// -/// - ``Trait/bug(_:_:)-2u8j9`` -/// - ``Trait/bug(_:_:)-7mo2w`` +/// - ``Trait/bug(_:_:)`` +/// - ``Trait/bug(_:id:_:)-10yf5`` +/// - ``Trait/bug(_:id:_:)-3vtpl`` public struct Bug { - /// The identifier of this bug in the associated bug-tracking system. + /// A URL linking to more information about the bug, if available. + /// + /// The value of this property represents a URL conforming to + /// [RFC 3986](https://www.ietf.org/rfc/rfc3986.txt). + public var url: String? + + /// A unique identifier in this bug's associated bug-tracking system, if + /// available. /// /// For more information on how the testing library interprets bug /// identifiers, see . - public var identifier: String + public var id: String? - /// An optional, user-specified comment describing this trait. - public var comment: Comment? + /// The human-readable title of the bug, if specified by the test author. + public var title: Comment? } -// MARK: - Equatable, Hashable, Comparable +// MARK: - Equatable, Hashable -extension Bug: Equatable, Hashable, Comparable { +extension Bug: Equatable, Hashable { public static func ==(lhs: Self, rhs: Self) -> Bool { - lhs.identifier == rhs.identifier + lhs.url == rhs.url && lhs.id == rhs.id } public func hash(into hasher: inout Hasher) { - hasher.combine(identifier) - } - - public static func <(lhs: Self, rhs: Self) -> Bool { - lhs.identifier < rhs.identifier + hasher.combine(url) + hasher.combine(id) } } // MARK: - Codable -extension Bug: Codable { - /// A temporary explicit implementation of this type's coding keys enumeration - /// to support the refactored form of `Bug` from [#412](https://github.com/apple/swift-testing/pull/412). - private enum _CodingKeys: String, CodingKey { - // Existing properties. - case identifier = "identifier" - case comment = "comment" - - // Proposed new properties. - case id = "id" - case url = "url" - case title = "title" - } - - public func encode(to encoder: any Encoder) throws { - var container = encoder.container(keyedBy: _CodingKeys.self) - - try container.encode(identifier, forKey: .identifier) - try container.encodeIfPresent(comment, forKey: .comment) - - // Temporary compatibility shims to support the refactored form of Bug from - // https://github.com/apple/swift-testing/pull/412 . - if identifier.contains(":") { - try container.encode(identifier, forKey: .url) - } else { - try container.encode(identifier, forKey: .id) - } - try container.encodeIfPresent(comment, forKey: .title) - } - - public init(from decoder: any Decoder) throws { - let container = try decoder.container(keyedBy: _CodingKeys.self) - identifier = try container.decodeIfPresent(String.self, forKey: .identifier) - // Temporary compatibility shims to support the refactored form of Bug - // from https://github.com/apple/swift-testing/pull/412 . - ?? container.decodeIfPresent(String.self, forKey: .id) - ?? container.decode(String.self, forKey: .url) - comment = try container.decodeIfPresent(Comment.self, forKey: .comment) - ?? container.decodeIfPresent(Comment.self, forKey: .title) - } -} +extension Bug: Codable {} // MARK: - Trait, TestTrait, SuiteTrait extension Bug: TestTrait, SuiteTrait { public var comments: [Comment] { - Array(comment) + Array(title) } } @@ -97,27 +62,41 @@ extension Trait where Self == Bug { /// Construct a bug to track with a test. /// /// - Parameters: - /// - identifier: The identifier of this bug in the associated bug-tracking - /// system. For more information on how this value is interpreted, see the - /// documentation for ``Bug``. - /// - comment: An optional, user-specified comment describing this trait. + /// - url: A URL referring to this bug in the associated bug-tracking + /// system. + /// - title: Optionally, the human-readable title of the bug. + /// + /// - Returns: An instance of ``Bug`` representing the specified bug. + public static func bug(_ url: _const String, _ title: Comment? = nil) -> Self { + Self(url: url, title: title) + } + + /// Construct a bug to track with a test. + /// + /// - Parameters: + /// - url: A URL referring to this bug in the associated bug-tracking + /// system. + /// - id: The unique identifier of this bug in its associated bug-tracking + /// system. + /// - title: Optionally, the human-readable title of the bug. /// /// - Returns: An instance of ``Bug`` representing the specified bug. - public static func bug(_ identifier: String, _ comment: Comment? = nil) -> Self { - Self(identifier: identifier, comment: comment) + public static func bug(_ url: _const String? = nil, id: some Numeric, _ title: Comment? = nil) -> Self { + Self(url: url, id: String(describing: id), title: title) } /// Construct a bug to track with a test. /// /// - Parameters: - /// - identifier: The identifier of this bug in the associated bug-tracking - /// system. For more information on how this value is interpreted, see the - /// documentation for ``Bug``. - /// - comment: An optional, user-specified comment describing this trait. + /// - url: A URL referring to this bug in the associated bug-tracking + /// system. + /// - id: The unique identifier of this bug in its associated bug-tracking + /// system. + /// - title: Optionally, the human-readable title of the bug. /// /// - Returns: An instance of ``Bug`` representing the specified bug. - public static func bug(_ identifier: some Numeric, _ comment: Comment? = nil) -> Self { - Self(identifier: String(describing: identifier), comment: comment) + public static func bug(_ url: _const String? = nil, id: _const String, _ title: Comment? = nil) -> Self { + Self(url: url, id: id, title: title) } } diff --git a/Sources/Testing/Traits/Comment.swift b/Sources/Testing/Traits/Comment.swift index 1c1cf4d20..afe1ed991 100644 --- a/Sources/Testing/Traits/Comment.swift +++ b/Sources/Testing/Traits/Comment.swift @@ -18,7 +18,8 @@ /// or `@Suite` attribute. See for more details. /// /// - Note: This type is not intended to reference bugs related to a test. -/// Instead, use ``Trait/bug(_:_:)-2u8j9`` or ``Trait/bug(_:_:)-7mo2w``. +/// Instead, use ``Trait/bug(_:_:)``, ``Trait/bug(_:id:_:)-10yf5``, or +/// ``Trait/bug(_:id:_:)-3vtpl``. public struct Comment: RawRepresentable, Sendable { /// The single comment string contained in this instance. /// @@ -121,7 +122,8 @@ extension Trait where Self == Comment { /// comment. /// /// - Note: This function is not intended to reference bugs related to a test. - /// Instead, use ``Trait/bug(_:_:)-2u8j9`` or ``Trait/bug(_:_:)-7mo2w``. + /// Instead, use ``Trait/bug(_:_:)``, ``Trait/bug(_:id:_:)-10yf5``, or + /// ``Trait/bug(_:id:_:)-3vtpl``. public static func comment(_ comment: String) -> Self { Self(rawValue: comment, kind: .trait) } diff --git a/Sources/TestingMacros/Support/DiagnosticMessage+Diagnosing.swift b/Sources/TestingMacros/Support/DiagnosticMessage+Diagnosing.swift index 6882c6c2f..9a100fec4 100644 --- a/Sources/TestingMacros/Support/DiagnosticMessage+Diagnosing.swift +++ b/Sources/TestingMacros/Support/DiagnosticMessage+Diagnosing.swift @@ -108,32 +108,14 @@ private func _diagnoseIssuesWithTagsTrait(_ traitExpr: FunctionCallExprSyntax, a /// - attribute: The `@Test` or `@Suite` attribute. /// - context: The macro context in which the expression is being parsed. private func _diagnoseIssuesWithBugTrait(_ traitExpr: FunctionCallExprSyntax, addedTo attribute: AttributeSyntax, in context: some MacroExpansionContext) { - // If the first argument to the .bug() trait is unlabelled and a string - // literal, check that it can be parsed as a URL or at least as an integer. - guard let arg = traitExpr.arguments.first.map(Argument.init), - arg.label == nil, - let stringLiteralExpr = arg.expression.as(StringLiteralExprSyntax.self), + // If the firstargument to the .bug() trait has no label and its value is a + // string literal, check that it can be parsed the way we expect. + guard let urlArg = traitExpr.arguments.first, urlArg.label == nil, + let stringLiteralExpr = urlArg.expression.as(StringLiteralExprSyntax.self), let urlString = stringLiteralExpr.representedLiteralValue else { return } - if UInt64(urlString) != nil { - // The entire URL string can be parsed as an integer, so allow it. Although - // the testing library prefers valid URLs here, some bug-tracking systems - // might not provide URLs, or might provide excessively long URLs, so we - // allow numeric identifiers as a fallback. - return - } - - if urlString.count > 3 && urlString.starts(with: "FB") && UInt64(urlString.dropFirst(2)) != nil { - // The string appears to be of the form "FBnnn...". Such strings are used by - // Apple to indicate issues filed using Feedback Assistant. Although we - // don't want to special-case every possible bug-tracking system out there, - // Feedback Assistant is very important to Apple so we're making an - // exception for it. - return - } - // We could use libcurl, libxml, or Windows' InternetCrackUrlW() to actually // parse the string and ensure it is a valid URL, however we could get // different results on different platforms. See the branch diff --git a/Sources/TestingMacros/Support/DiagnosticMessage.swift b/Sources/TestingMacros/Support/DiagnosticMessage.swift index 4ea7e42be..22ffba151 100644 --- a/Sources/TestingMacros/Support/DiagnosticMessage.swift +++ b/Sources/TestingMacros/Support/DiagnosticMessage.swift @@ -567,7 +567,7 @@ struct DiagnosticMessage: SwiftDiagnostics.DiagnosticMessage { return Self( syntax: Syntax(urlExpr), message: #"URL "\#(urlString)" is invalid and cannot be used with trait '\#(traitName.trimmed)' in attribute \#(_macroName(attribute))"#, - severity: .error, + severity: .warning, fixIts: [ FixIt( message: MacroExpansionFixItMessage(#"Replace "\#(urlString)" with URL"#), diff --git a/Tests/TestingMacrosTests/TestDeclarationMacroTests.swift b/Tests/TestingMacrosTests/TestDeclarationMacroTests.swift index ba2ca4e14..0efc93308 100644 --- a/Tests/TestingMacrosTests/TestDeclarationMacroTests.swift +++ b/Tests/TestingMacrosTests/TestDeclarationMacroTests.swift @@ -357,13 +357,15 @@ struct TestDeclarationMacroTests { @Test("Valid bug identifiers are allowed", arguments: [ - #"@Test(.bug(12345)) func f() {}"#, - #"@Test(.bug("12345")) func f() {}"#, + #"@Test(.bug(id: 12345)) func f() {}"#, + #"@Test(.bug(id: "12345")) func f() {}"#, #"@Test(.bug("mailto:a@example.com")) func f() {}"#, #"@Test(.bug("rdar:12345")) func f() {}"#, #"@Test(.bug("rdar://12345")) func f() {}"#, - #"@Test(.bug("FB12345")) func f() {}"#, + #"@Test(.bug(id: "FB12345")) func f() {}"#, #"@Test(.bug("https://github.com/apple/swift-testing/issues/12345")) func f() {}"#, + #"@Test(.bug("https://github.com/apple/swift-testing/issues/12345", id: "12345")) func f() {}"#, + #"@Test(.bug("https://github.com/apple/swift-testing/issues/12345", id: 12345)) func f() {}"#, #"@Test(Bug.bug("https://github.com/apple/swift-testing/issues/12345")) func f() {}"#, #"@Test(Testing.Bug.bug("https://github.com/apple/swift-testing/issues/12345")) func f() {}"#, #"@Test(Bug.bug("https://github.com/apple/swift-testing/issues/12345", "here's what happened...")) func f() {}"#, @@ -375,21 +377,19 @@ struct TestDeclarationMacroTests { #expect(diagnostics.isEmpty) } - @Test("Invalid bug identifiers are detected", + @Test("Invalid bug URLs are detected", arguments: [ - "12345 ", "here's what happened...", "🌯", "mailto: a@example.com", - "FB", "FBabc", "FB1", + "mailto: a@example.com", "example.com", ] ) - func invalidBugIdentifiers(id: String) throws { + func invalidBugURLs(id: String) throws { let input = #"@Test(.bug("\#(id)")) func f() {}"# let (_, diagnostics) = try parse(input) #expect(diagnostics.count > 0) for diagnostic in diagnostics { - #expect(diagnostic.diagMessage.severity == .error) + #expect(diagnostic.diagMessage.severity == .warning) #expect(diagnostic.message == #"URL "\#(id)" is invalid and cannot be used with trait 'bug' in attribute 'Test'"#) } } - } diff --git a/Tests/TestingTests/EventRecorderTests.swift b/Tests/TestingTests/EventRecorderTests.swift index ba6fe6375..dedf59ecd 100644 --- a/Tests/TestingTests/EventRecorderTests.swift +++ b/Tests/TestingTests/EventRecorderTests.swift @@ -304,7 +304,6 @@ struct EventRecorderTests { #endif #if canImport(Foundation) || canImport(FoundationXML) - @Test( "JUnitXMLRecorder outputs valid XML", .bug("https://github.com/apple/swift-testing/issues/254") diff --git a/Tests/TestingTests/Test.SnapshotTests.swift b/Tests/TestingTests/Test.SnapshotTests.swift index 447ef3846..2487a91a2 100644 --- a/Tests/TestingTests/Test.SnapshotTests.swift +++ b/Tests/TestingTests/Test.SnapshotTests.swift @@ -94,7 +94,7 @@ struct Test_SnapshotTests { #expect(snapshot.associatedBugs.first == Self.bug) } - private static let bug: Bug = Bug.bug(12345, "Lorem ipsum") + private static let bug: Bug = Bug.bug(id: 12345, "Lorem ipsum") @available(_clockAPI, *) @Test("timeLimit property", _timeLimitIfAvailable(minutes: 999_999_999)) diff --git a/Tests/TestingTests/Traits/BugTests.swift b/Tests/TestingTests/Traits/BugTests.swift index 57389b3f2..739acb672 100644 --- a/Tests/TestingTests/Traits/BugTests.swift +++ b/Tests/TestingTests/Traits/BugTests.swift @@ -12,70 +12,82 @@ @Suite("Bug Tests", .tags(.traitRelated)) struct BugTests { + @Test(".bug() with URL string") + func bugFactoryMethodWithURLString() throws { + let trait = Bug.bug("https://www.example.com/12345", "Lorem ipsum") + #expect((trait as Any) is Bug) + #expect(trait.url == "https://www.example.com/12345") + #expect(trait.title == "Lorem ipsum") + #expect(trait.comments == ["Lorem ipsum"]) + } + @Test(".bug() with String") func bugFactoryMethodWithString() throws { - let trait = Bug.bug("12345", "Lorem ipsum") + let trait = Bug.bug(id: "12345", "Lorem ipsum") #expect((trait as Any) is Bug) - #expect(trait.identifier == "12345") - #expect(trait.comment == "Lorem ipsum") + #expect(trait.id == "12345") + #expect(trait.title == "Lorem ipsum") #expect(trait.comments == ["Lorem ipsum"]) } @Test(".bug() with SignedInteger") func bugFactoryMethodWithSignedInteger() throws { - let trait = Bug.bug(12345) + let trait = Bug.bug(id: 12345) #expect((trait as Any) is Bug) - #expect(trait.identifier == "12345") - #expect(trait.comment == nil) + #expect(trait.id == "12345") + #expect(trait.title == nil) #expect(trait.comments.isEmpty) } @Test(".bug() with UnsignedInteger") func bugFactoryMethodWithUnsignedInteger() throws { - let trait = Bug.bug(UInt32(12345), "Lorem ipsum") + let trait = Bug.bug(id: UInt32(12345), "Lorem ipsum") #expect((trait as Any) is Bug) - #expect(trait.identifier == "12345") - #expect(trait.comment == "Lorem ipsum") + #expect(trait.id == "12345") + #expect(trait.title == "Lorem ipsum") #expect(trait.comments == ["Lorem ipsum"]) } - @Test("Comparing Bug instances") - func bugComparison() throws { - let lhs = Bug.bug(12345) - let rhs = Bug.bug("67890") - + @Test("Comparing Bug instances", + arguments: [ + Bug.bug(id: 12345), + .bug("https://www.example.com/67890"), + ], [ + Bug.bug("67890"), + .bug("https://www.example.com/12345"), + ] + ) + func bugComparison(lhs: Bug, rhs: Bug) throws { #expect(lhs != rhs) - #expect(lhs < rhs) - #expect(rhs > lhs) } @Test(".bug() is not recursively applied") func bugIsNotRecursive() async throws { - let trait = Bug.bug(12345) + let trait = Bug.bug(id: 12345) #expect(!trait.isRecursive) } @Test("Test.associatedBugs property") func testAssociatedBugsProperty() { - let test = Test(.bug(12345), .disabled(), .bug(67890), .bug(24680), .bug(54321)) {} + let test = Test(.bug(id: 12345), .disabled(), .bug(id: 67890), .bug(id: 24680), .bug(id: 54321)) {} let bugIdentifiers = test.associatedBugs #expect(bugIdentifiers.count == 4) - #expect(bugIdentifiers[0].identifier == "12345") - #expect(bugIdentifiers[1].identifier == "67890") - #expect(bugIdentifiers[2].identifier == "24680") - #expect(bugIdentifiers[3].identifier == "54321") + #expect(bugIdentifiers[0].id == "12345") + #expect(bugIdentifiers[1].id == "67890") + #expect(bugIdentifiers[2].id == "24680") + #expect(bugIdentifiers[3].id == "54321") } @Test("Bug hashing") func hashing() { - let traits: Set = [.bug(12345), .bug(12345), .bug(12345), .bug("67890")] - #expect(traits.count == 2) + let traits: Set = [.bug(id: 12345), .bug(id: "12345"), .bug(id: 12345), .bug(id: "67890"), .bug("https://www.example.com/12345")] + #expect(traits.count == 3) } #if canImport(Foundation) @Test("Encoding/decoding") func encodingAndDecoding() throws { - let original = Bug.bug(12345, "Lorem ipsum") + let original = Bug.bug(id: 12345, "Lorem ipsum") let copy = try JSON.encodeAndDecode(original) #expect(original == copy) }