XCTest入門Part2 (Swift) ~非同期編~

#はじめに
今回は、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となってしまいます。

#テストしてみる
##テスト対象のメソッド
今回は、以下のメソッドをテストしてみたいと思います。

```swift:UrlSessionManager.swift
    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となっていました。気づくのにしばらくかかった、、）

```swift:UrlSessionManagerTests.swift
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でも軽く触れたので詳細説明は割愛させていただきます。

``````swift:UrlSessionManagerTests.swift
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で非同期処理のテストをする方法を書きました。
非同期処理はよく使うと思うので、ちゃんとテストコード書いてあげましょう!