File: 0001-refactor-bug-inits.md

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (168 lines) | stat: -rw-r--r-- 7,477 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# Dedicated `.bug()` functions for URLs and IDs

* Proposal: [SWT-0001](0001-refactor-bug-inits.md)
* Authors: [Jonathan Grynspan](https://github.com/grynspan)
* Status: **Accepted**
* Implementation: [swiftlang/swift-testing#401](https://github.com/swiftlang/swift-testing/pull/401)
* Review: ([pitch](https://forums.swift.org/t/pitch-dedicated-bug-functions-for-urls-and-ids/71842)), ([acceptance](https://forums.swift.org/t/swt-0001-dedicated-bug-functions-for-urls-and-ids/71842/2))

## Introduction

One of the features of swift-testing is a test traits system that allows
associating metadata with a test suite or test function. One trait in
particular, `.bug()`, has the potential for integration with development tools
but needs some refinement before integration would be practical.

## Motivation

A test author can associate a bug (AKA issue, problem, ticket, etc.) with a test
using the `.bug()` trait, to which they pass an "identifier" for the bug. The
swift-testing team's intent here was that a test author would pass the unique
identifier of the bug in the test author's preferred bug-tracking system (e.g.
GitHub Issues, Bugzilla, etc.) and that any tooling built around this trait
would be able to infer where the bug was located and how to view it.

It became clear immediately that a generic system for looking up bugs by unique
identifier in an arbitrary and unspecified database wouldn't be a workable
solution. So we modified the description of `.bug()` to explain that, if the
identifier passed to it was a valid URL, then it would be "interpreted" as a URL
and that tools could be designed to open that URL as needed.

This design change then placed the burden of parsing each `.bug()` trait and
potentially mapping it to a URL on tools. swift-testing itself avoids linking to
or using Foundation API such as `URL`, so checking for a valid URL inside the
testing library was not feasible either.

## Proposed solution

To solve the underlying problem and allow test authors to specify a URL when
available, or just an opaque identifier otherwise, we propose splitting the
`.bug()` function up into two overloads:

- The first overload takes a URL string and additional optional metadata;
- The second overload takes a bug identifier as an opaque string or integer and,
  optionally, a URL string.
  
Test authors are then free to specify any combination of URL and opaque
identifier depending on the information they have available and their specific
needs. Tools authors are free to consume either or both of these properties and
present them where appropriate.

## Detailed design

The `Bug` trait type and `.bug()` trait factory function shall be refactored
thusly:

```swift
/// A type representing a bug report tracked by a test.
///
/// To add this trait to a test, use one of the following functions:
///
/// - ``Trait/bug(_:_:)``
/// - ``Trait/bug(_:id:_:)-10yf5``
/// - ``Trait/bug(_:id:_:)-3vtpl``
public struct Bug: TestTrait, SuiteTrait, Equatable, Hashable, Codable {
  /// 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 <doc:BugIdentifiers>.
  public var id: String?

  /// The human-readable title of the bug, if specified by the test author.
  public var title: Comment?
}

extension Trait where Self == Bug {
  /// Construct a bug to track with a test.
  ///
  /// - Parameters:
  ///   - 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

  /// 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(_ url: _const String? = nil, id: some Numeric, _ title: Comment? = nil) -> Self

  /// 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(_ url: _const String? = nil, id: _const String, _ title: Comment? = nil) -> Self
}
```

The `@Test` and `@Suite` macros have already been modified so that they perform
basic validation of a URL string passed as input and emit a diagnostic if the
URL string appears malformed. 

## Source compatibility

This change is expected to be source-breaking for test authors who have already
adopted the existing `.bug()` functions. This change is source-breaking for code
that directly refers to these functions by their signatures. This change is
source-breaking for code that uses the `identifier` property of the `Bug` type
or expects it to contain a URL.

## Integration with supporting tools

Tools that integrate with swift-testing and provide lists of tests or record
results after tests have run can use the `Bug` trait on tests to present
relevant identifiers and/or URLs to users.

Tools that use the experimental event stream output feature of the testing
library will need a JSON schema for bug traits on tests. This work is tracked in
a separate upcoming proposal.

## Alternatives considered

- Inferring whether or not a bug identifier was a URL by parsing it at runtime
  in tools. As discussed above, this option would require every tool that
  integrates with swift-testing to provide its own URL-parsing logic.
  
- Using different argument labels (e.g. the label `url` for the URL argument
  and/or no label for the `id` argument.) We felt that URLs, which are
  recognizable by their general structure, did not need labels. At least one
  argument must have a label to avoid ambiguous resolution of the `.bug()`
  function at compile time.

- Inferring whether or not a bug identifier was a URL by parsing it at compile-
  time or at runtime using `Foundation.URL` or libcurl. swift-testing actively
  avoids linking to Foundation if at all possible, and libcurl would be a
  platform-specific solution (Windows doesn't ship with libcurl, but does have
  `InternetCrackUrlW()` whose parsing engine differs.) We also run the risk of
  inappropriately interpreting some arbitrary bug identifier as a URL when it is
  not meant to be parsed that way.

- Removing the `.bug()` trait. We see this particular trait as having strong
  potential for integration with tools and for use by test authors; removing it
  because we can't reliably parse URLs would be unfortunate.

## Acknowledgments

Thanks to the swift-testing team and managers for their contributions! Thanks to
our community for the initial feedback around this feature.