Skip to content

Commit 03afefd

Browse files
authored
Merge pull request #27 from apple/jgrynspan/112974442-sourcelocation-arg
Allow specifying the source location of `#expect()` and `#require()`.
2 parents d9b8eba + b29ab93 commit 03afefd

File tree

10 files changed

+130
-46
lines changed

10 files changed

+130
-46
lines changed

Sources/Testing/Expectations/Expectation+Macro.swift

Lines changed: 54 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,15 @@
1515
/// - Parameters:
1616
/// - condition: The condition to be evaluated.
1717
/// - comment: A comment describing the expectation.
18+
/// - sourceLocation: The source location to which recorded expectations and
19+
/// issues should be attributed.
1820
///
1921
/// If `condition` evaluates to `false`, an ``Issue`` is recorded for the test
2022
/// that is running in the current task.
2123
@freestanding(expression) public macro expect(
2224
_ condition: Bool,
23-
_ comment: @autoclosure () -> Comment? = nil
25+
_ comment: @autoclosure () -> Comment? = nil,
26+
sourceLocation: SourceLocation = SourceLocation()
2427
) = #externalMacro(module: "TestingMacros", type: "ExpectMacro")
2528

2629
/// Check that an expectation has passed after a condition has been evaluated
@@ -29,6 +32,8 @@
2932
/// - Parameters:
3033
/// - condition: The condition to be evaluated.
3134
/// - comment: A comment describing the expectation.
35+
/// - sourceLocation: The source location to which recorded expectations and
36+
/// issues should be attributed.
3237
///
3338
/// - Throws: An instance of ``ExpectationFailedError`` if `condition` evaluates
3439
/// to `false`.
@@ -38,7 +43,8 @@
3843
/// ``ExpectationFailedError`` is thrown.
3944
@freestanding(expression) public macro require(
4045
_ condition: Bool,
41-
_ comment: @autoclosure () -> Comment? = nil
46+
_ comment: @autoclosure () -> Comment? = nil,
47+
sourceLocation: SourceLocation = SourceLocation()
4248
) = #externalMacro(module: "TestingMacros", type: "RequireMacro")
4349

4450
// MARK: - Optional checking
@@ -48,6 +54,8 @@
4854
/// - Parameters:
4955
/// - optionalValue: The optional value to be unwrapped.
5056
/// - comment: A comment describing the expectation.
57+
/// - sourceLocation: The source location to which recorded expectations and
58+
/// issues should be attributed.
5159
///
5260
/// - Returns: The unwrapped value of `value`.
5361
///
@@ -57,7 +65,8 @@
5765
/// in the current task and an instance of ``ExpectationFailedError`` is thrown.
5866
@freestanding(expression) public macro require<T>(
5967
_ optionalValue: T?,
60-
_ comment: @autoclosure () -> Comment? = nil
68+
_ comment: @autoclosure () -> Comment? = nil,
69+
sourceLocation: SourceLocation = SourceLocation()
6170
) -> T = #externalMacro(module: "TestingMacros", type: "RequireMacro")
6271

6372
// MARK: - Matching errors by type
@@ -69,6 +78,8 @@
6978
/// `expression` could throw _any_ error, or the specific type of thrown
7079
/// error is unimportant, pass `any Error.self`.
7180
/// - comment: A comment describing the expectation.
81+
/// - sourceLocation: The source location to which recorded expectations and
82+
/// issues should be attributed.
7283
/// - expression: The expression to be evaluated.
7384
///
7485
/// Use this overload of `#expect()` when the expression `expression` _should_
@@ -87,18 +98,22 @@
8798
/// discarded.
8899
///
89100
/// If the thrown error need only equal another instance of [`Error`](https://developer.apple.com/documentation/swift/error),
90-
/// use ``expect(throws:_:performing:)-1s3lx`` instead. If `expression` should
91-
/// _never_ throw any error, use ``expect(throws:_:performing:)-jtjw`` instead.
101+
/// use ``expect(throws:_:sourceLocation:performing:)-1xr34`` instead. If
102+
/// `expression` should _never_ throw any error, use
103+
/// ``expect(throws:_:sourceLocation:performing:)-5lzjz`` instead.
92104
@freestanding(expression) public macro expect<E, R>(
93105
throws errorType: E.Type,
94106
_ comment: @autoclosure () -> Comment? = nil,
107+
sourceLocation: SourceLocation = SourceLocation(),
95108
performing expression: () async throws -> R
96109
) = #externalMacro(module: "TestingMacros", type: "ExpectMacro") where E: Error
97110

98111
/// Check that an expression never throws an error.
99112
///
100113
/// - Parameters:
101114
/// - comment: A comment describing the expectation.
115+
/// - sourceLocation: The source location to which recorded expectations and
116+
/// issues should be attributed.
102117
/// - expression: The expression to be evaluated.
103118
///
104119
/// Use this overload of `#expect()` when the expression `expression` should
@@ -123,12 +138,13 @@
123138
/// naturally.
124139
///
125140
/// If the thrown error need only be an instance of a particular type, use
126-
/// ``expect(throws:_:performing:)-2j0od`` instead. If the thrown error need
127-
/// only equal another instance of [`Error`](https://developer.apple.com/documentation/swift/error),
128-
/// use ``expect(throws:_:performing:)-1s3lx`` instead.
141+
/// ``expect(throws:_:sourceLocation:performing:)-79piu`` instead. If the thrown
142+
/// error need only equal another instance of [`Error`](https://developer.apple.com/documentation/swift/error),
143+
/// use ``expect(throws:_:sourceLocation:performing:)-1xr34`` instead.
129144
@freestanding(expression) public macro expect<R>(
130145
throws _: Never.Type,
131146
_ comment: @autoclosure () -> Comment? = nil,
147+
sourceLocation: SourceLocation = SourceLocation(),
132148
performing expression: () async throws -> R
133149
) = #externalMacro(module: "TestingMacros", type: "ExpectMacro")
134150

@@ -140,6 +156,8 @@
140156
/// `expression` could throw _any_ error, or the specific type of thrown
141157
/// error is unimportant, pass `any Error.self`.
142158
/// - comment: A comment describing the expectation.
159+
/// - sourceLocation: The source location to which recorded expectations and
160+
/// issues should be attributed.
143161
/// - expression: The expression to be evaluated.
144162
///
145163
/// - Throws: An instance of ``ExpectationFailedError`` if `expression` does not
@@ -161,13 +179,14 @@
161179
/// is thrown. Any value returned by `expression` is discarded.
162180
///
163181
/// If the thrown error need only equal another instance of [`Error`](https://developer.apple.com/documentation/swift/error),
164-
/// use ``require(throws:_:performing:)-84jir`` instead.
182+
/// use ``require(throws:_:sourceLocation:performing:)-7v83e`` instead.
165183
///
166184
/// If `expression` should _never_ throw, simply invoke the code without using
167185
/// this macro. The test will then fail if an error is thrown.
168186
@freestanding(expression) public macro require<E, R>(
169187
throws errorType: E.Type,
170188
_ comment: @autoclosure () -> Comment? = nil,
189+
sourceLocation: SourceLocation = SourceLocation(),
171190
performing expression: () async throws -> R
172191
) = #externalMacro(module: "TestingMacros", type: "RequireMacro") where E: Error
173192

@@ -176,6 +195,8 @@
176195
///
177196
/// - Parameters:
178197
/// - comment: A comment describing the expectation.
198+
/// - sourceLocation: The source location to which recorded expectations and
199+
/// issues should be attributed.
179200
/// - expression: The expression to be evaluated.
180201
///
181202
/// - Throws: An instance of ``ExpectationFailedError`` if `expression` throws
@@ -184,6 +205,7 @@
184205
@freestanding(expression) public macro require<R>(
185206
throws _: Never.Type,
186207
_ comment: @autoclosure () -> Comment? = nil,
208+
sourceLocation: SourceLocation = SourceLocation(),
187209
performing expression: () async throws -> R
188210
) = #externalMacro(module: "TestingMacros", type: "RequireMacro")
189211

@@ -194,6 +216,8 @@
194216
/// - Parameters:
195217
/// - error: The error that is expected to be thrown.
196218
/// - comment: A comment describing the expectation.
219+
/// - sourceLocation: The source location to which recorded expectations and
220+
/// issues should be attributed.
197221
/// - expression: The expression to be evaluated.
198222
///
199223
/// Use this overload of `#expect()` when the expression `expression` _should_
@@ -211,11 +235,13 @@
211235
/// in the current task. Any value returned by `expression` is discarded.
212236
///
213237
/// If the thrown error need only be an instance of a particular type, use
214-
/// ``expect(throws:_:performing:)-2j0od`` instead. If `expression` should
215-
/// _never_ throw any error, use ``expect(throws:_:performing:)-jtjw`` instead.
238+
/// ``expect(throws:_:sourceLocation:performing:)-79piu`` instead. If
239+
/// `expression` should _never_ throw any error, use
240+
/// ``expect(throws:_:sourceLocation:performing:)-5lzjz`` instead.
216241
@freestanding(expression) public macro expect<E, R>(
217242
throws error: E,
218243
_ comment: @autoclosure () -> Comment? = nil,
244+
sourceLocation: SourceLocation = SourceLocation(),
219245
performing expression: () async throws -> R
220246
) = #externalMacro(module: "TestingMacros", type: "ExpectMacro") where E: Error & Equatable
221247

@@ -225,6 +251,8 @@
225251
/// - Parameters:
226252
/// - error: The error that is expected to be thrown.
227253
/// - comment: A comment describing the expectation.
254+
/// - sourceLocation: The source location to which recorded expectations and
255+
/// issues should be attributed.
228256
/// - expression: The expression to be evaluated.
229257
///
230258
/// - Throws: An instance of ``ExpectationFailedError`` if `expression` does not
@@ -246,10 +274,11 @@
246274
/// Any value returned by `expression` is discarded.
247275
///
248276
/// If the thrown error need only be an instance of a particular type, use
249-
/// ``require(throws:_:performing:)-8762f`` instead.
277+
/// ``require(throws:_:sourceLocation:performing:)-76bjn`` instead.
250278
@freestanding(expression) public macro require<E, R>(
251279
throws error: E,
252280
_ comment: @autoclosure () -> Comment? = nil,
281+
sourceLocation: SourceLocation = SourceLocation(),
253282
performing expression: () async throws -> R
254283
) = #externalMacro(module: "TestingMacros", type: "RequireMacro") where E: Error & Equatable
255284

@@ -259,6 +288,8 @@
259288
///
260289
/// - Parameters:
261290
/// - comment: A comment describing the expectation.
291+
/// - sourceLocation: The source location to which recorded expectations and
292+
/// issues should be attributed.
262293
/// - expression: The expression to be evaluated.
263294
/// - errorMatcher: A closure to invoke when `expression` throws an error that
264295
/// indicates if it matched or not.
@@ -283,12 +314,14 @@
283314
/// discarded.
284315
///
285316
/// If the thrown error need only be an instance of a particular type, use
286-
/// ``expect(throws:_:performing:)-2j0od`` instead. If the thrown error need
287-
/// only equal another instance of [`Error`](https://developer.apple.com/documentation/swift/error),
288-
/// use ``expect(throws:_:performing:)-1s3lx`` instead. If an error should
289-
/// _never_ be thrown, use ``expect(throws:_:performing:)-jtjw`` instead.
317+
/// ``expect(throws:_:sourceLocation:performing:)-79piu`` instead. If the thrown
318+
/// error need only equal another instance of [`Error`](https://developer.apple.com/documentation/swift/error),
319+
/// use ``expect(throws:_:sourceLocation:performing:)-1xr34`` instead. If an
320+
/// error should _never_ be thrown, use
321+
/// ``expect(throws:_:sourceLocation:performing:)-5lzjz`` instead.
290322
@freestanding(expression) public macro expect<R>(
291323
_ comment: @autoclosure () -> Comment? = nil,
324+
sourceLocation: SourceLocation = SourceLocation(),
292325
performing expression: () async throws -> R,
293326
throws errorMatcher: (any Error) async throws -> Bool
294327
) = #externalMacro(module: "TestingMacros", type: "ExpectMacro")
@@ -298,6 +331,8 @@
298331
///
299332
/// - Parameters:
300333
/// - comment: A comment describing the expectation.
334+
/// - sourceLocation: The source location to which recorded expectations and
335+
/// issues should be attributed.
301336
/// - expression: The expression to be evaluated.
302337
/// - errorMatcher: A closure to invoke when `expression` throws an error that
303338
/// indicates if it matched or not.
@@ -326,14 +361,15 @@
326361
/// discarded.
327362
///
328363
/// If the thrown error need only be an instance of a particular type, use
329-
/// ``require(throws:_:performing:)-8762f`` instead. If the thrown error need
364+
/// ``require(throws:_:sourceLocation:performing:)-76bjn`` instead. If the thrown error need
330365
/// only equal another instance of [`Error`](https://developer.apple.com/documentation/swift/error),
331-
/// use ``require(throws:_:performing:)-84jir`` instead.
366+
/// use ``require(throws:_:sourceLocation:performing:)-7v83e`` instead.
332367
///
333368
/// If `expression` should _never_ throw, simply invoke the code without using
334369
/// this macro. The test will then fail if an error is thrown.
335370
@freestanding(expression) public macro require<R>(
336371
_ comment: @autoclosure () -> Comment? = nil,
372+
sourceLocation: SourceLocation = SourceLocation(),
337373
performing expression: () async throws -> R,
338374
throws errorMatcher: (any Error) async throws -> Bool
339375
) = #externalMacro(module: "TestingMacros", type: "RequireMacro")

Sources/Testing/Issues/Issue+Recording.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ extension Issue {
8181
/// - Returns: The issue that was recorded.
8282
///
8383
/// Use this function if, while running a test, an issue occurs that cannot be
84-
/// represented as an expectation (using the ``expect(_:_:)`` or
85-
/// ``require(_:_:)-6lago`` macros.)
84+
/// represented as an expectation (using the ``expect(_:_:sourceLocation:)``
85+
/// or ``require(_:_:sourceLocation:)-5l63q`` macros.)
8686
@discardableResult public static func record(
8787
_ comment: Comment? = nil,
8888
fileID: String = #fileID,

Sources/Testing/Issues/Issue.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public struct Issue: Sendable {
1717
case unconditional
1818

1919
/// An issue due to a failed expectation, such as those produced by
20-
/// ``expect(_:_:)``.
20+
/// ``expect(_:_:sourceLocation:)``.
2121
///
2222
/// - Parameters:
2323
/// - expectation: The expectation that failed.

Sources/Testing/Testing.docc/ExpectThrows.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,17 +29,17 @@ runtime not to mark the test as failing when those issues occur.
2929

3030
### Validating that errors are thrown
3131

32-
- ``expect(throws:_:performing:)-2j0od``
33-
- ``expect(throws:_:performing:)-1s3lx``
34-
- ``expect(_:performing:throws:)``
35-
- ``require(throws:_:performing:)-8762f``
36-
- ``require(throws:_:performing:)-84jir``
37-
- ``require(_:performing:throws:)``
32+
- ``expect(throws:_:sourceLocation:performing:)-79piu``
33+
- ``expect(throws:_:sourceLocation:performing:)-1xr34``
34+
- ``expect(_:sourceLocation:performing:throws:)``
35+
- ``require(throws:_:sourceLocation:performing:)-76bjn``
36+
- ``require(throws:_:sourceLocation:performing:)-7v83e``
37+
- ``require(_:sourceLocation:performing:throws:)``
3838

3939
### Validating that errors are not thrown
4040

41-
- ``expect(throws:_:performing:)-jtjw``
42-
- ``require(throws:_:performing:)-4a80i``
41+
- ``expect(throws:_:sourceLocation:performing:)-5lzjz``
42+
- ``require(throws:_:sourceLocation:performing:)-36uzc``
4343

4444
### Recording known issues in tests
4545

Sources/Testing/Testing.docc/Expectations.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ built-in expectation APIs.
2121

2222
### Validating behavior using expectations
2323

24-
- ``expect(_:_:)``
25-
- ``require(_:_:)-6lago``
26-
- ``require(_:_:)-3wq2g``
24+
- ``expect(_:_:sourceLocation:)``
25+
- ``require(_:_:sourceLocation:)-5l63q``
26+
- ``require(_:_:sourceLocation:)-6w9oo``
2727

2828
### Validating asynchronous behavior using confirmations
2929

Sources/Testing/Testing.docc/MigratingFromXCTest.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -193,9 +193,10 @@ see <doc:DefiningTests>.
193193
XCTest uses a family of approximately 40 functions to assert test requirements.
194194
These functions are collectively referred to as
195195
[`XCTAssert()`](https://developer.apple.com/documentation/xctest/1500669-xctassert).
196-
The testing library has two replacements, ``expect(_:_:)`` and
197-
``require(_:_:)-6lago``. They both behave similarly to `XCTAssert()` except that
198-
``require(_:_:)-6lago`` will throw an error if its condition is not met:
196+
The testing library has two replacements, ``expect(_:_:sourceLocation:)`` and
197+
``require(_:_:sourceLocation:)-5l63q``. They both behave similarly to
198+
`XCTAssert()` except that ``require(_:_:sourceLocation:)-5l63q`` will throw an
199+
error if its condition is not met:
199200

200201
@Row {
201202
@Column {
@@ -232,8 +233,8 @@ The testing library has two replacements, ``expect(_:_:)`` and
232233

233234
XCTest also has a function, [`XCTUnwrap()`](https://developer.apple.com/documentation/xctest/3380195-xctunwrap),
234235
that tests if an optional value is `nil` and throws an error if it is. When
235-
using the testing library, you can use ``require(_:_:)-3wq2g`` with optional
236-
expressions to unwrap them:
236+
using the testing library, you can use ``require(_:_:sourceLocation:)-6w9oo``
237+
with optional expressions to unwrap them:
237238

238239
@Row {
239240
@Column {

0 commit comments

Comments
 (0)