#はじめに
今回は、XCTestで非同期処理のテストをしてみます。
ちなみに、前回はXCTestの基礎を記載しました。
http://qiita.com/okuderap/items/97f9d6026d0da59fef38
こちらも参考にしてみてください。
XCTestでカバレッジを確認する方法
http://qiita.com/okuderap/items/de574685592fe0bee8ea
#非同期処理のテスト
XCTestでは非同期処理のテストをすることもできるんです。
非同期処理のテストにはXCTestExpectationを使います。
let imageDownloadExpectation: XCTestExpectation? =
self.expectationWithDescription("download Image")
こんな感じで定義してあげます。テストコードの中に複数のexpectationを定義することもできます。
descriptionには、非同期処理の期待する結果を書いてあげれば良いかと。
期待する結果になったところで
XCTestExpectationのfulfillを呼びます。
imageDownloadExpectation?.fulfill()
それから、タイムアウトの時間を決めます。
waitForExpectationsWithTimeout(timeout: 0.05, handler:nil)
こんな感じでタイムアウトの設定をします。handlerは、今回はnilにしておきます。
定義したXCTestExpectationの数分だけfulfillが呼ばれて
且つタイムアウトしていなければtest Succeededとなります。
どちらか一方でも条件を満たすことができなければtest Failedとなってしまいます。
#テストしてみる
##テスト対象のメソッド
今回は、以下のメソッドをテストしてみたいと思います。
func downloadImage(urlString: String,
completionHandler: ((NSData?, NSURLResponse?, NSError?) -> Void)) {
guard let url = NSURL(string: urlString) else {
return
}
let request = NSURLRequest(URL: url)
let session = NSURLSession(configuration: .defaultSessionConfiguration())
let task = session.dataTaskWithRequest(request, completionHandler: completionHandler)
task.resume()
}
##テストコードを書いてみる
実際にテストコードを書いてみます。
ポイントとなるのは上述の通り
- XCTestExpectationの定義
- XCTestExpectationのfulfill呼び出し
- waitForExpectationsWithTimeoutでタイムアウトの設定
こんな感じです。
また、定義したXCTestExpectationの数分だけfulfillを呼ぶということも重要です。
(私は、はじめtest用urlの配列の長さ分だけループさせていたためfulfillを複数回呼んでtest Failedとなっていました。気づくのにしばらくかかった、、)
import XCTest
@testable import SwiftXCTestSample
class UrlSessionManagerTests: XCTestCase {
let urlSessionManager = UrlSessionManager()
override func setUp() {
super.setUp()
}
override func tearDown() {
super.tearDown()
}
func testDownloadImage() {
let imageDownloadExpectation: XCTestExpectation? = self.expectationWithDescription("download Image")
let urlString = "http://www.smartdt.jp/images/common/logo.png"
urlSessionManager.downloadImage(urlString, completionHandler:{ (data, response, error) in
XCTAssertNil(error)
XCTAssertNotNil(data)
imageDownloadExpectation?.fulfill()
})
self.waitForExpectationsWithTimeout(0.02, handler: nil)
}
こんな感じのコードで非同期処理のテストをすることができます。
##せっかくなのでパフォーマンステストも書いてみる
せっかく非同期処理のテストをするので、パフォーマンステストもしてみます。
パフォーマンステストについては、前回のXCTest入門Part1でも軽く触れたので詳細説明は割愛させていただきます。
func testPerformanceDownloadImage() {
self.measureBlock { [weak self] () in
guard let weakSelf = self else {
return
}
let imageDownloadExpectation: XCTestExpectation? = weakSelf.expectationWithDescription("download Image")
let testUrlString = "http://www.smartdt.jp/images/common/logo.png"
weakSelf.urlSessionManager.downloadImage(testUrlString, completionHandler:{ (data, response, error) in
XCTAssertNil(error)
XCTAssertNotNil(data)
imageDownloadExpectation?.fulfill()
})
weakSelf.waitForExpectationsWithTimeout(0.02, handler: nil)
}
}
```
#さいごに
今回はXCTestで非同期処理のテストをする方法を書きました。
非同期処理はよく使うと思うので、ちゃんとテストコード書いてあげましょう!