@@ -10,13 +10,146 @@ See https://swift.org/LICENSE.txt for license information
10
10
See https://swift.org/CONTRIBUTORS.txt for Swift project authors
11
11
-->
12
12
13
- Highlight known issues when running tests.
13
+ Mark issues as known when running tests.
14
14
15
15
## Overview
16
16
17
- The testing library provides a function, ` withKnownIssue() ` , that you
18
- use to mark issues as known. Use this function to inform the testing library
19
- at runtime not to mark the test as failing when issues occur.
17
+ The testing library provides several functions named ` withKnownIssue() ` that
18
+ you can use to mark issues as known. Use them to inform the testing library that
19
+ a test should not be marked as failing if only known issues are recorded.
20
+
21
+ ### Mark an expectation failure as known
22
+
23
+ Consider a test function with a single expectation:
24
+
25
+ ``` swift
26
+ @Test func grillHeating () throws {
27
+ var foodTruck = FoodTruck ()
28
+ try foodTruck.startGrill ()
29
+ #expect (foodTruck.grill .isHeating ) // ❌ Expectation failed
30
+ }
31
+ ```
32
+
33
+ If the value of the ` isHeating ` property is ` false ` , ` #expect ` will record an
34
+ issue. If you cannot fix the underlying problem, you can surround the failing
35
+ code in a closure passed to ` withKnownIssue() ` :
36
+
37
+ ``` swift
38
+ @Test func grillHeating () throws {
39
+ var foodTruck = FoodTruck ()
40
+ try foodTruck.startGrill ()
41
+ withKnownIssue (" Propane tank is empty" ) {
42
+ #expect (foodTruck.grill .isHeating ) // Known issue
43
+ }
44
+ }
45
+ ```
46
+
47
+ The issue recorded by ` #expect ` will then be considered "known" and the test
48
+ will not be marked as a failure. You may include an optional comment to explain
49
+ the problem or provide context.
50
+
51
+ ### Mark a thrown error as known
52
+
53
+ If an ` Error ` is caught by the closure passed to ` withKnownIssue() ` , the issue
54
+ representing that caught error will be marked as known. Continuing the previous
55
+ example, suppose the problem is that the ` startGrill() ` function is throwing an
56
+ error. You can apply ` withKnownIssue() ` to this situation as well:
57
+
58
+ ``` swift
59
+ @Test func grillHeating () {
60
+ var foodTruck = FoodTruck ()
61
+ withKnownIssue {
62
+ try foodTruck.startGrill () // Known issue
63
+ #expect (foodTruck.grill .isHeating )
64
+ }
65
+ }
66
+ ```
67
+
68
+ Because all errors thrown from the closure are caught and interpreted as known
69
+ issues, the ` withKnownIssue() ` function is not throwing. Consequently, any
70
+ subsequent code which depends on the throwing call having succeeded (such as the
71
+ ` #expect ` after ` startGrill() ` ) must be included in the closure to avoid
72
+ additional issues.
73
+
74
+ - Note: ` withKnownIssue() ` is recommended instead of ` #expect(throws:) ` for any
75
+ error which is considered a known issue so that the test status and results
76
+ will reflect the situation more accurately.
77
+
78
+ ### Match a specific issue
79
+
80
+ By default, ` withKnownIssue() ` considers all issues recorded while invoking the
81
+ body closure known. If multiple issues may be recorded, you can pass a trailing
82
+ closure labeled ` matching: ` which will be called once for each recorded issue
83
+ to determine whether it should be treated as known:
84
+
85
+ ``` swift
86
+ @Test func batteryLevel () throws {
87
+ var foodTruck = FoodTruck ()
88
+ try withKnownIssue {
89
+ let batteryLevel = try #require (foodTruck.batteryLevel ) // Known
90
+ #expect (batteryLevel >= 0.8 ) // Not considered known
91
+ } matching : { issue in
92
+ guard case .expectationFailed (let expectation) = issue.kind else {
93
+ return false
94
+ }
95
+ return expectation.isRequired
96
+ }
97
+ }
98
+ ```
99
+
100
+ ### Resolve a known issue
101
+
102
+ If there are no issues recorded while calling ` function ` , ` withKnownIssue() `
103
+ will record a distinct issue about the lack of any issues having been recorded.
104
+ This notifies you that the underlying problem may have been resolved so that you
105
+ can investigate and consider removing ` withKnownIssue() ` if it's no longer
106
+ necessary.
107
+
108
+ ### Handle a nondeterministic failure
109
+
110
+ If ` withKnownIssue() ` sometimes succeeds but other times records an issue
111
+ indicating there were no known issues, this may indicate a nondeterministic
112
+ failure or a "flaky" test.
113
+
114
+ The first step in resolving a nondeterministic test failure is to analyze the
115
+ code being tested and determine the source of the unpredictable behavior. If
116
+ you discover a bug such as a race condition, the ideal resolution is to fix
117
+ the underlying problem so that the code always behaves consistently even if
118
+ it continues to exhibit the known issue.
119
+
120
+ If the underlying problem only occurs in certain circumstances, consider
121
+ including a precondition. For example, if the grill only fails to heat when
122
+ there's no propane, you can pass a trailing closure labeled ` when: ` which
123
+ determines whether issues recorded in the body closure should be considered
124
+ known:
125
+
126
+ ``` swift
127
+ @Test func grillHeating () throws {
128
+ var foodTruck = FoodTruck ()
129
+ try foodTruck.startGrill ()
130
+ withKnownIssue {
131
+ // Only considered known when hasPropane == false
132
+ #expect (foodTruck.grill .isHeating )
133
+ } when : {
134
+ ! hasPropane
135
+ }
136
+ }
137
+ ```
138
+
139
+ If the underlying problem is unpredictable and fails at random, you can pass
140
+ ` isIntermittent: true ` to let the testing library know that it will not always
141
+ occur. Then, the testing library will not record an issue when zero known issues
142
+ are recorded:
143
+
144
+ ``` swift
145
+ @Test func grillHeating () throws {
146
+ var foodTruck = FoodTruck ()
147
+ try foodTruck.startGrill ()
148
+ withKnownIssue (isIntermittent : true ) {
149
+ #expect (foodTruck.grill .isHeating )
150
+ }
151
+ }
152
+ ```
20
153
21
154
## Topics
22
155
0 commit comments