Skip to content

Commit fe6ec41

Browse files
authored
Merge pull request swiftlang#2462 from drodriguez/migrate-unwrapped-to-xctunwrap
[gardening] Migrate from unwrapped() to XCTUnwrap()
2 parents bd2b4e0 + 9b83d91 commit fe6ec41

24 files changed

+177
-183
lines changed

Docs/Testing.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ swift-corelibs-foundation uses XCTest for its own test suite. This document expl
77
### In brief
88

99
* Tests should fail rather than crashing; swift-corelibs-xctest does not implement any crash recovery
10-
* You should avoid forced optional unwrapping (e.g.: `aValue!`). Use `try aValue.unwrapped()` instead
10+
* You should avoid forced optional unwrapping (e.g.: `aValue!`). Use `try XCTUnwrap(aValue)` instead
1111
* You can test code that is expected to crash; you must mark the whole body of the test method with `assertCrashes(within:)`
1212
* If a test or a portion of a test is giving the build trouble, use `testExpectedToFail` and write a bug
1313

@@ -19,7 +19,7 @@ Due to this, it is important to avoid crashing in test code, and to properly han
1919

2020
#### Avoiding Forced Unwrapping
2121

22-
Forced unwrapping is easily the easiest way to crash the test process, and should be avoided. We have an ergonomic replacement in the form of the `.unwrapped()` extension method on the `Optional` type.
22+
Forced unwrapping is easily the easiest way to crash the test process, and should be avoided. XCTest have an ergonomic replacement in the form of the `XCTUnwrap()` function.
2323

2424
The following code is a liability and code review should flag it:
2525

@@ -34,14 +34,14 @@ func testSomeInterestingAPI() {
3434
Instead:
3535

3636
1. Change the test method to throw errors by adding the `throws` clause. Tests that throw errors will fail and stop the first time an error is thrown, so plan accordingly, but a thrown error will not stop the test run, merely fail this test.
37-
2. Change the forced unwrapping to `try ….unwrapped()`.
37+
2. Change the forced unwrapping to `try XCTUnwrap(…)`.
3838

3939
For example, the code above can be fixed as follows:
4040

4141
```swift
4242
func testSomeInterestingAPI() throws { // Step 1: Add 'throws'
4343
// Step 2: Replace the unwrap.
44-
let x = try interestingAPI.someOptionalProperty.unwrapped()
44+
let x = try XCTUnwrap(interestingAPI.someOptionalProperty)
4545

4646
XCTAssertEqual(x, 42, "The correct answer is present")
4747
}

TestFoundation/FixtureValues.swift

+4-4
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ enum Fixtures {
4141
attrs3Maybe = nil
4242
}
4343

44-
let attrs3 = try attrs3Maybe.unwrapped()
44+
let attrs3 = try XCTUnwrap(attrs3Maybe)
4545

4646
string.setAttributes(attrs1, range: NSMakeRange(1, string.length - 2))
4747
string.setAttributes(attrs2, range: NSMakeRange(2, 2))
@@ -147,7 +147,7 @@ enum Fixtures {
147147
static let textCheckingResultSimpleRegex = TypedFixture<NSTextCheckingResult>("NSTextCheckingResult-SimpleRegex") {
148148
let string = "aaa"
149149
let regexp = try NSRegularExpression(pattern: "aaa", options: [])
150-
let result = try regexp.matches(in: string, range: NSRange(string.startIndex ..< string.endIndex, in: string)).first.unwrapped()
150+
let result = try XCTUnwrap(regexp.matches(in: string, range: NSRange(string.startIndex ..< string.endIndex, in: string)).first)
151151

152152
return result
153153
}
@@ -156,15 +156,15 @@ enum Fixtures {
156156
static let textCheckingResultExtendedRegex = TypedFixture<NSTextCheckingResult>("NSTextCheckingResult-ExtendedRegex") {
157157
let string = "aaaaaa"
158158
let regexp = try NSRegularExpression(pattern: "a(a(a(a(a(a)))))", options: [])
159-
let result = try regexp.matches(in: string, range: NSRange(string.startIndex ..< string.endIndex, in: string)).first.unwrapped()
159+
let result = try XCTUnwrap(regexp.matches(in: string, range: NSRange(string.startIndex ..< string.endIndex, in: string)).first)
160160

161161
return result
162162
}
163163

164164
static let textCheckingResultComplexRegex = TypedFixture<NSTextCheckingResult>("NSTextCheckingResult-ComplexRegex") {
165165
let string = "aaaaaaaaa"
166166
let regexp = try NSRegularExpression(pattern: "a(a(a(a(a(a(a(a(a))))))))", options: [])
167-
let result = try regexp.matches(in: string, range: NSRange(string.startIndex ..< string.endIndex, in: string)).first.unwrapped()
167+
let result = try XCTUnwrap(regexp.matches(in: string, range: NSRange(string.startIndex ..< string.endIndex, in: string)).first)
168168

169169
return result
170170
}

TestFoundation/TestCachedURLResponse.swift

+14-14
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
class TestCachedURLResponse : XCTestCase {
1111
func test_copy() throws {
12-
let url = try URL(string: "http://example.com/").unwrapped()
12+
let url = try XCTUnwrap(URL(string: "http://example.com/"))
1313
let response = URLResponse(url: url, mimeType: nil, expectedContentLength: -1, textEncodingName: nil)
1414
let bytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
1515
let data = Data(bytes: bytes, count: bytes.count)
@@ -26,7 +26,7 @@ class TestCachedURLResponse : XCTestCase {
2626
}
2727

2828
func test_initDefaultUserInfoAndStoragePolicy() throws {
29-
let url = try URL(string: "http://example.com/").unwrapped()
29+
let url = try XCTUnwrap(URL(string: "http://example.com/"))
3030
let response = URLResponse(url: url, mimeType: nil, expectedContentLength: -1, textEncodingName: nil)
3131
let bytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
3232
let data = Data(bytes: bytes, count: bytes.count)
@@ -39,7 +39,7 @@ class TestCachedURLResponse : XCTestCase {
3939
}
4040

4141
func test_initDefaultUserInfo() throws {
42-
let url = try URL(string: "http://example.com/").unwrapped()
42+
let url = try XCTUnwrap(URL(string: "http://example.com/"))
4343
let response = URLResponse(url: url, mimeType: nil, expectedContentLength: -1, textEncodingName: nil)
4444
let bytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
4545
let data = Data(bytes: bytes, count: bytes.count)
@@ -53,7 +53,7 @@ class TestCachedURLResponse : XCTestCase {
5353
}
5454

5555
func test_initWithoutDefaults() throws {
56-
let url = try URL(string: "http://example.com/").unwrapped()
56+
let url = try XCTUnwrap(URL(string: "http://example.com/"))
5757
let response = URLResponse(url: url, mimeType: nil, expectedContentLength: -1, textEncodingName: nil)
5858
let bytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
5959
let data = Data(bytes: bytes, count: bytes.count)
@@ -68,7 +68,7 @@ class TestCachedURLResponse : XCTestCase {
6868
}
6969

7070
func test_equalWithTheSameInstance() throws {
71-
let url = try URL(string: "http://example.com/").unwrapped()
71+
let url = try XCTUnwrap(URL(string: "http://example.com/"))
7272
let response = URLResponse(url: url, mimeType: nil, expectedContentLength: -1, textEncodingName: nil)
7373
let bytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
7474
let data = Data(bytes: bytes, count: bytes.count)
@@ -80,7 +80,7 @@ class TestCachedURLResponse : XCTestCase {
8080
}
8181

8282
func test_equalWithUnrelatedObject() throws {
83-
let url = try URL(string: "http://example.com/").unwrapped()
83+
let url = try XCTUnwrap(URL(string: "http://example.com/"))
8484
let response = URLResponse(url: url, mimeType: nil, expectedContentLength: -1, textEncodingName: nil)
8585
let bytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
8686
let data = Data(bytes: bytes, count: bytes.count)
@@ -92,19 +92,19 @@ class TestCachedURLResponse : XCTestCase {
9292
}
9393

9494
func test_equalCheckingResponse() throws {
95-
let url1 = try URL(string: "http://example.com/").unwrapped()
95+
let url1 = try XCTUnwrap(URL(string: "http://example.com/"))
9696
let response1 = URLResponse(url: url1, mimeType: nil, expectedContentLength: -1, textEncodingName: nil)
9797
let bytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
9898
let data = Data(bytes: bytes, count: bytes.count)
9999
let userInfo: [AnyHashable: Any] = ["Key1": "Value1", "Key2": "Value2"]
100100
let storagePolicy = URLCache.StoragePolicy.allowedInMemoryOnly
101101
let cachedResponse1 = CachedURLResponse(response: response1, data: data, userInfo: userInfo, storagePolicy: storagePolicy)
102102

103-
let url2 = try URL(string: "http://example.com/second").unwrapped()
103+
let url2 = try XCTUnwrap(URL(string: "http://example.com/second"))
104104
let response2 = URLResponse(url: url2, mimeType: nil, expectedContentLength: -1, textEncodingName: nil)
105105
let cachedResponse2 = CachedURLResponse(response: response2, data: data, userInfo: userInfo, storagePolicy: storagePolicy)
106106

107-
let url3 = try URL(string: "http://example.com/").unwrapped()
107+
let url3 = try XCTUnwrap(URL(string: "http://example.com/"))
108108
let response3 = URLResponse(url: url3, mimeType: nil, expectedContentLength: -1, textEncodingName: nil)
109109
let cachedResponse3 = CachedURLResponse(response: response3, data: data, userInfo: userInfo, storagePolicy: storagePolicy)
110110

@@ -115,7 +115,7 @@ class TestCachedURLResponse : XCTestCase {
115115
}
116116

117117
func test_equalCheckingData() throws {
118-
let url = try URL(string: "http://example.com/").unwrapped()
118+
let url = try XCTUnwrap(URL(string: "http://example.com/"))
119119
let response = URLResponse(url: url, mimeType: nil, expectedContentLength: -1, textEncodingName: nil)
120120
let bytes1: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
121121
let data1 = Data(bytes: bytes1, count: bytes1.count)
@@ -138,7 +138,7 @@ class TestCachedURLResponse : XCTestCase {
138138
}
139139

140140
func test_equalCheckingStoragePolicy() throws {
141-
let url = try URL(string: "http://example.com/").unwrapped()
141+
let url = try XCTUnwrap(URL(string: "http://example.com/"))
142142
let response = URLResponse(url: url, mimeType: nil, expectedContentLength: -1, textEncodingName: nil)
143143
let bytes: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
144144
let data = Data(bytes: bytes, count: bytes.count)
@@ -159,15 +159,15 @@ class TestCachedURLResponse : XCTestCase {
159159
}
160160

161161
func test_hash() throws {
162-
let url1 = try URL(string: "http://example.com/").unwrapped()
162+
let url1 = try XCTUnwrap(URL(string: "http://example.com/"))
163163
let response1 = URLResponse(url: url1, mimeType: nil, expectedContentLength: -1, textEncodingName: nil)
164164
let bytes1: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
165165
let data1 = Data(bytes: bytes1, count: bytes1.count)
166166
let userInfo1: [AnyHashable: Any] = ["Key1": "Value1", "Key2": "Value2"]
167167
let storagePolicy1 = URLCache.StoragePolicy.allowedInMemoryOnly
168168
let cachedResponse1 = CachedURLResponse(response: response1, data: data1, userInfo: userInfo1, storagePolicy: storagePolicy1)
169169

170-
let url2 = try URL(string: "http://example.com/").unwrapped()
170+
let url2 = try XCTUnwrap(URL(string: "http://example.com/"))
171171
let response2 = URLResponse(url: url2, mimeType: nil, expectedContentLength: -1, textEncodingName: nil)
172172
let bytes2: [UInt8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
173173
let data2 = Data(bytes: bytes2, count: bytes2.count)
@@ -176,7 +176,7 @@ class TestCachedURLResponse : XCTestCase {
176176
let cachedResponse2 = CachedURLResponse(response: response2, data: data2, userInfo: userInfo2, storagePolicy: storagePolicy2)
177177

178178
// Ideally, this cached response should have a different hash.
179-
let url3 = try URL(string: "http://example.com/second").unwrapped()
179+
let url3 = try XCTUnwrap(URL(string: "http://example.com/second"))
180180
let response3 = URLResponse(url: url3, mimeType: nil, expectedContentLength: -1, textEncodingName: nil)
181181
let bytes3: [UInt8] = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
182182
let data3 = Data(bytes: bytes3, count: bytes3.count)

TestFoundation/TestCalendar.swift

+5-5
Original file line numberDiff line numberDiff line change
@@ -234,21 +234,21 @@ class TestCalendar: XCTestCase {
234234
// Check that date(from:) does not change the timeZone of the calendar
235235
let df = DateFormatter()
236236
df.dateFormat = "yyyy-MM-dd"
237-
df.timeZone = try TimeZone(identifier: "UTC").unwrapped()
237+
df.timeZone = try XCTUnwrap(TimeZone(identifier: "UTC"))
238238

239239
var calendar = Calendar(identifier: .gregorian)
240240
calendar.locale = Locale(identifier: "en_US_POSIX")
241-
calendar.timeZone = try TimeZone(secondsFromGMT: 0).unwrapped()
241+
calendar.timeZone = try XCTUnwrap(TimeZone(secondsFromGMT: 0))
242242

243243
let calendarCopy = calendar
244244
XCTAssertEqual(calendarCopy.timeZone.identifier, "GMT")
245245
XCTAssertEqual(calendarCopy.timeZone.description, "GMT (fixed)")
246246

247-
let dc = try calendarCopy.dateComponents(in: TimeZone(identifier: "America/New_York").unwrapped(), from: df.date(from: "2019-01-01").unwrapped())
247+
let dc = try calendarCopy.dateComponents(in: XCTUnwrap(TimeZone(identifier: "America/New_York")), from: XCTUnwrap(df.date(from: "2019-01-01")))
248248
XCTAssertEqual(calendarCopy.timeZone.identifier, "GMT")
249249
XCTAssertEqual(calendarCopy.timeZone.description, "GMT (fixed)")
250250

251-
let dt = try calendarCopy.date(from: dc).unwrapped()
251+
let dt = try XCTUnwrap(calendarCopy.date(from: dc))
252252
XCTAssertEqual(dt.description, "2019-01-01 00:00:00 +0000")
253253
XCTAssertEqual(calendarCopy.timeZone.identifier, "GMT")
254254
XCTAssertEqual(calendarCopy.timeZone.description, "GMT (fixed)")
@@ -498,7 +498,7 @@ class TestNSDateComponents: XCTestCase {
498498
let date3 = Date(timeIntervalSince1970: 46570600.45678)
499499

500500
var calendar = Calendar.current
501-
calendar.timeZone = try TimeZone(abbreviation: "UTC").unwrapped()
501+
calendar.timeZone = try XCTUnwrap(TimeZone(abbreviation: "UTC"))
502502

503503
let diff1 = calendar.dateComponents([.nanosecond], from: date1, to: date2)
504504
XCTAssertEqual(diff1.nanosecond, 1230003)

TestFoundation/TestDateFormatter.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -419,12 +419,12 @@ class TestDateFormatter: XCTestCase {
419419
formatter.dateFormat = "yyyy-MM-dd"
420420

421421
XCTAssertNil(formatter.date(from: "2018-03-09T10:25:16+01:00"))
422-
let d1 = try formatter.date(from: "2018-03-09").unwrapped()
422+
let d1 = try XCTUnwrap(formatter.date(from: "2018-03-09"))
423423
XCTAssertEqual(d1.description, "2018-03-09 00:00:00 +0000")
424424

425425
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
426426
XCTAssertNil(formatter.date(from: "2018-03-09"))
427-
let d2 = try formatter.date(from: "2018-03-09T10:25:16+01:00").unwrapped()
427+
let d2 = try XCTUnwrap(formatter.date(from: "2018-03-09T10:25:16+01:00"))
428428
XCTAssertEqual(d2.description, "2018-03-09 09:25:16 +0000")
429429
}
430430

@@ -471,7 +471,7 @@ class TestDateFormatter: XCTestCase {
471471
let formatter = DateFormatter()
472472
formatter.timeZone = TimeZone(identifier: "CET")
473473
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
474-
let date = try formatter.date(from: "2019-05-05T12:52:10").unwrapped()
474+
let date = try XCTUnwrap(formatter.date(from: "2019-05-05T12:52:10"))
475475

476476
let applySettings: [(String, (DateFormatter) -> Void)] =
477477
[(".timeZone", {

TestFoundation/TestDateIntervalFormatter.swift

+6-6
Original file line numberDiff line numberDiff line change
@@ -107,14 +107,14 @@ class TestDateIntervalFormatter: XCTestCase {
107107
let result = formatter.string(from: date, to: date)
108108
result.assertContainsInOrder(requiresLastToBeAtEnd: true, "February 4", "2001", "5:20:00 PM", "Greenwich Mean Time")
109109

110-
let firstFebruary = try result.range(of: "February").unwrapped()
110+
let firstFebruary = try XCTUnwrap(result.range(of: "February"))
111111
XCTAssertNil(result[firstFebruary.upperBound...].range(of: "February")) // February appears only once.
112112
}
113113

114114
func testStringFromDateIntervalAcrossThreeMillionSeconds() throws {
115115
let interval = DateInterval(start: Date(timeIntervalSinceReferenceDate: 0), duration: 3e6)
116116

117-
let result = try formatter.string(from: interval).unwrapped()
117+
let result = try XCTUnwrap(formatter.string(from: interval))
118118
result.assertContainsInOrder("January 1", "2001", "12:00:00 AM", "Greenwich Mean Time",
119119
"February 4", "2001", "5:20:00 PM", "Greenwich Mean Time")
120120
}
@@ -195,7 +195,7 @@ class TestDateIntervalFormatter: XCTestCase {
195195
let result = formatter.string(from: older, to: newer)
196196
result.assertContainsInOrder(requiresLastToBeAtEnd: true, "January", "1", "2001", "12:00:00 AM", "5:00:00 AM", "GMT")
197197

198-
let firstJanuary = try result.range(of: "January").unwrapped()
198+
let firstJanuary = try XCTUnwrap(result.range(of: "January"))
199199
XCTAssertNil(result[firstJanuary.upperBound...].range(of: "January")) // January appears only once.
200200
}
201201

@@ -217,7 +217,7 @@ class TestDateIntervalFormatter: XCTestCase {
217217
let result = formatter.string(from: older, to: newer)
218218
result.assertContainsInOrder(requiresLastToBeAtEnd: true, "January", "1", "2001", "12:00:00 AM", "6:00:00 PM", "GMT")
219219

220-
let firstJanuary = try result.range(of: "January").unwrapped()
220+
let firstJanuary = try XCTUnwrap(result.range(of: "January"))
221221
XCTAssertNil(result[firstJanuary.upperBound...].range(of: "January")) // January appears only once.
222222
}
223223

@@ -229,8 +229,8 @@ class TestDateIntervalFormatter: XCTestCase {
229229
XCTAssertNotNil(lhs)
230230
XCTAssertNotNil(rhs)
231231

232-
let a = try lhs.unwrapped()
233-
let b = try rhs.unwrapped()
232+
let a = try XCTUnwrap(lhs)
233+
let b = try XCTUnwrap(rhs)
234234

235235
XCTAssertEqual(a.dateStyle, b.dateStyle, message())
236236
XCTAssertEqual(a.timeStyle, b.timeStyle, message())

TestFoundation/TestDecimal.swift

+4-4
Original file line numberDiff line numberDiff line change
@@ -602,10 +602,10 @@ class TestDecimal: XCTestCase {
602602
XCTAssertEqual(NSDecimalNumber(decimal: Decimal(UInt64.min)).description, UInt64.min.description)
603603
XCTAssertEqual(NSDecimalNumber(decimal: Decimal(UInt64.max)).description, UInt64.max.description)
604604

605-
XCTAssertEqual(try NSDecimalNumber(decimal: Decimal(string: "12.34").unwrapped()).description, "12.34")
606-
XCTAssertEqual(try NSDecimalNumber(decimal: Decimal(string: "0.0001").unwrapped()).description, "0.0001")
607-
XCTAssertEqual(try NSDecimalNumber(decimal: Decimal(string: "-1.0002").unwrapped()).description, "-1.0002")
608-
XCTAssertEqual(try NSDecimalNumber(decimal: Decimal(string: "0.0").unwrapped()).description, "0")
605+
XCTAssertEqual(NSDecimalNumber(decimal: try XCTUnwrap(Decimal(string: "12.34"))).description, "12.34")
606+
XCTAssertEqual(NSDecimalNumber(decimal: try XCTUnwrap(Decimal(string: "0.0001"))).description, "0.0001")
607+
XCTAssertEqual(NSDecimalNumber(decimal: try XCTUnwrap(Decimal(string: "-1.0002"))).description, "-1.0002")
608+
XCTAssertEqual(NSDecimalNumber(decimal: try XCTUnwrap(Decimal(string: "0.0"))).description, "0")
609609
}
610610

611611
func test_PositivePowers() {

0 commit comments

Comments
 (0)