Skip to content

Commit

Permalink
Merge pull request swiftlang#2462 from drodriguez/migrate-unwrapped-t…
Browse files Browse the repository at this point in the history
…o-xctunwrap

[gardening] Migrate from unwrapped() to XCTUnwrap()
  • Loading branch information
drodriguez authored Aug 23, 2019
2 parents bd2b4e0 + 9b83d91 commit fe6ec41
Show file tree
Hide file tree
Showing 24 changed files with 177 additions and 183 deletions.
8 changes: 4 additions & 4 deletions Docs/Testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ swift-corelibs-foundation uses XCTest for its own test suite. This document expl
### In brief

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

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

#### Avoiding Forced Unwrapping

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.
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.

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

Expand All @@ -34,14 +34,14 @@ func testSomeInterestingAPI() {
Instead:

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.
2. Change the forced unwrapping to `try ….unwrapped()`.
2. Change the forced unwrapping to `try XCTUnwrap(…)`.

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

```swift
func testSomeInterestingAPI() throws { // Step 1: Add 'throws'
// Step 2: Replace the unwrap.
let x = try interestingAPI.someOptionalProperty.unwrapped()
let x = try XCTUnwrap(interestingAPI.someOptionalProperty)

XCTAssertEqual(x, 42, "The correct answer is present")
}
Expand Down
8 changes: 4 additions & 4 deletions TestFoundation/FixtureValues.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ enum Fixtures {
attrs3Maybe = nil
}

let attrs3 = try attrs3Maybe.unwrapped()
let attrs3 = try XCTUnwrap(attrs3Maybe)

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

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

return result
}

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

return result
}
Expand Down
28 changes: 14 additions & 14 deletions TestFoundation/TestCachedURLResponse.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

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

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

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

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

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

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

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

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

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

Expand All @@ -115,7 +115,7 @@ class TestCachedURLResponse : XCTestCase {
}

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

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

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

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

// Ideally, this cached response should have a different hash.
let url3 = try URL(string: "http://example.com/second").unwrapped()
let url3 = try XCTUnwrap(URL(string: "http://example.com/second"))
let response3 = URLResponse(url: url3, mimeType: nil, expectedContentLength: -1, textEncodingName: nil)
let bytes3: [UInt8] = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
let data3 = Data(bytes: bytes3, count: bytes3.count)
Expand Down
10 changes: 5 additions & 5 deletions TestFoundation/TestCalendar.swift
Original file line number Diff line number Diff line change
Expand Up @@ -234,21 +234,21 @@ class TestCalendar: XCTestCase {
// Check that date(from:) does not change the timeZone of the calendar
let df = DateFormatter()
df.dateFormat = "yyyy-MM-dd"
df.timeZone = try TimeZone(identifier: "UTC").unwrapped()
df.timeZone = try XCTUnwrap(TimeZone(identifier: "UTC"))

var calendar = Calendar(identifier: .gregorian)
calendar.locale = Locale(identifier: "en_US_POSIX")
calendar.timeZone = try TimeZone(secondsFromGMT: 0).unwrapped()
calendar.timeZone = try XCTUnwrap(TimeZone(secondsFromGMT: 0))

let calendarCopy = calendar
XCTAssertEqual(calendarCopy.timeZone.identifier, "GMT")
XCTAssertEqual(calendarCopy.timeZone.description, "GMT (fixed)")

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

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

var calendar = Calendar.current
calendar.timeZone = try TimeZone(abbreviation: "UTC").unwrapped()
calendar.timeZone = try XCTUnwrap(TimeZone(abbreviation: "UTC"))

let diff1 = calendar.dateComponents([.nanosecond], from: date1, to: date2)
XCTAssertEqual(diff1.nanosecond, 1230003)
Expand Down
6 changes: 3 additions & 3 deletions TestFoundation/TestDateFormatter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -419,12 +419,12 @@ class TestDateFormatter: XCTestCase {
formatter.dateFormat = "yyyy-MM-dd"

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

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

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

let applySettings: [(String, (DateFormatter) -> Void)] =
[(".timeZone", {
Expand Down
12 changes: 6 additions & 6 deletions TestFoundation/TestDateIntervalFormatter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -107,14 +107,14 @@ class TestDateIntervalFormatter: XCTestCase {
let result = formatter.string(from: date, to: date)
result.assertContainsInOrder(requiresLastToBeAtEnd: true, "February 4", "2001", "5:20:00 PM", "Greenwich Mean Time")

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

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

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

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

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

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

Expand All @@ -229,8 +229,8 @@ class TestDateIntervalFormatter: XCTestCase {
XCTAssertNotNil(lhs)
XCTAssertNotNil(rhs)

let a = try lhs.unwrapped()
let b = try rhs.unwrapped()
let a = try XCTUnwrap(lhs)
let b = try XCTUnwrap(rhs)

XCTAssertEqual(a.dateStyle, b.dateStyle, message())
XCTAssertEqual(a.timeStyle, b.timeStyle, message())
Expand Down
8 changes: 4 additions & 4 deletions TestFoundation/TestDecimal.swift
Original file line number Diff line number Diff line change
Expand Up @@ -602,10 +602,10 @@ class TestDecimal: XCTestCase {
XCTAssertEqual(NSDecimalNumber(decimal: Decimal(UInt64.min)).description, UInt64.min.description)
XCTAssertEqual(NSDecimalNumber(decimal: Decimal(UInt64.max)).description, UInt64.max.description)

XCTAssertEqual(try NSDecimalNumber(decimal: Decimal(string: "12.34").unwrapped()).description, "12.34")
XCTAssertEqual(try NSDecimalNumber(decimal: Decimal(string: "0.0001").unwrapped()).description, "0.0001")
XCTAssertEqual(try NSDecimalNumber(decimal: Decimal(string: "-1.0002").unwrapped()).description, "-1.0002")
XCTAssertEqual(try NSDecimalNumber(decimal: Decimal(string: "0.0").unwrapped()).description, "0")
XCTAssertEqual(NSDecimalNumber(decimal: try XCTUnwrap(Decimal(string: "12.34"))).description, "12.34")
XCTAssertEqual(NSDecimalNumber(decimal: try XCTUnwrap(Decimal(string: "0.0001"))).description, "0.0001")
XCTAssertEqual(NSDecimalNumber(decimal: try XCTUnwrap(Decimal(string: "-1.0002"))).description, "-1.0002")
XCTAssertEqual(NSDecimalNumber(decimal: try XCTUnwrap(Decimal(string: "0.0"))).description, "0")
}

func test_PositivePowers() {
Expand Down
Loading

0 comments on commit fe6ec41

Please sign in to comment.