配列を返すメソッド等のテストで、配列の中身をアサートするとき、
以下のようにアクセスすると、クラッシュする場合がある。
let Items = [
"hoge",
"fuga",
]
XCTAssertEqual(Items.count, 3)
XCTAssertEqual(Items[0], "hoge")
XCTAssertEqual(Items[1], "fuga")
XCTAssertEqual(Items[2], "piyo") // Thread 1 : Fatal error : Index out of range
テストがクラッシュすると、重要な情報が失われる。
この場合、Xcodeの画面上で表示される情報は、範囲外のインデックス指定でクラッシュしたことのみで、
1つ目のアサーションXCTAssertEqual(Items.count, 3)
が失敗していることは表示されない。
クラッシュ自体はテストの失敗と見なすことができるが、失敗に関しての情報は多ければ多いほど、
その対処は容易になる。
以下のようにCollectionを拡張することで、安全にアクセスすることができる。
extension Collection {
subscript(safe index: Index) -> Element? {
return indices.contains(index) ? self[index] : nil
}
}
safe subscript を使えば、範囲外のインデックスを指定した時にnil
を返す。
これを使用して、テストを書くと以下のようになる。
let Items = [
"hoge",
"fuga",
]
XCTAssertEqual(Items.count, 3) //XCTAssertEqual failed: ("1") is not equal to ("3")
XCTAssertEqual(Items[safe: 0], "hoge")
XCTAssertEqual(Items[safe: 1], "fuga")
XCTAssertEqual(Items[safe: 2], "piyo") //XCTAssertEqual failed: (nil) is not equal to ("piyo")
このように、クラッシュせずにアサーションの結果が表示される。