Swift3.0、Alamofire4.4で今日の天気を取得して、テストする

使ったライブラリなど

  • Swift(3.0)
  • Alamofire (4.4.0)
  • SwiftyJSON (3.1.4)
  • OpenWeatherMap

やったこと・やりたかったこと

 東京都の今日の天気をOpenWeatherMapから取得して、アラートで表示する。その後、XCTestを使って単体テストとUIテストを書いて、テストが成功することを確認しました。
 xcodeのテストツールを使いたかったたため、簡単なサンプルを書いて検証しました。

↓からgit clone できます。 * https://github.com/yanaoto/XCTestSample

テストするコード(getWeather(:))

func getWeather(closure:(String) -> Void) {  
        let urlStr = "http://api.openweathermap.org/data/2.5/forecast?q=Tokyo&APPID=${APPID}"
        Alamofire.request(urlStr, method: .get, parameters: nil, encoding: JSONEncoding.default, headers: nil).responseJSON { (response:DataResponse<Any>) in
            switch(response.result) {
            case .success(_):
                if let jsonResult = response.result.value as? [String: Any] {
                    let json = JSON(jsonResult)
                    json["list"].forEach{(_, weathers) in
                        weathers["weather"].forEach{(_, descriptions) in
                            // アラートを表示
                            self.showAlert(message: descriptions["description"].string!)
                        }
                    }
                }
                break
            case .failure(_):
                print("error")
                print(response.result.error ?? "Faild")
                break
            }
        }
    }

ユニットテスト

 Swiftは manual mocking という手法を取ります。 これはテスト対象クラスを継承したクラスを定義し、テストしたいメソッドをオーバーライドします。 返却値等を固定文字列とすることで、スタブの作成となります。

    func testShowWeather() {
        class VCMock:ViewController {
            override func getWeather(closure:(String) -> Void) {
                closure("test weather")
            }
        }

        let vcm:VCMock = VCMock()
        vcm.showWeather()
    }

UI テスト

UI recordingというxcodeの機能を使って、自動的に作成してくれます。

    func testShowWeatherAlert() {
        let app = XCUIApplication()
        let okButton = app.alerts["確認"].buttons["OK"]
        okButton.tap()
        app.buttons["Get Weather"].tap()
        okButton.tap()

    }

まとめ

テストについてわかりやすく書いてあった、SwiftでXCTestを使って単体テストとUIテストをしてみよう!を参考にして、テストの書き方だけ知りたかったのですが、AlamofireのSwift3.0対応により、サンプルコードが古くなっていて動きませんでした。 また、今回はあまり複雑な処理でテストを行っていないため、ユニットテストもUIテストも直感的で簡単に使えました。これから深く知ろうとすると、躓くこともあるかもしれませんが、

補足(SwiftyJSONを使ったコードと使わないコードを比較)

SwiftyJSONを使わずに、ディクショナリーから取り出した場合。
最初、SwiftyJSONを使わずにコードを書いていましたが、使った方がスッキリ書けました。

ViewController.swift(SwiftyJSONなし)  
ViewController.swift(SwiftyJSONあり)

                 if let jsonResult = response.result.value as? [String: Any] {
-                    if let datas = jsonResult["list"] as? [[String:Any]] {
-                        for data in datas {
-                            if let weathers = data["weather"] as? [[String:Any]] {
-                                for weather in weathers {
-                                    if let description = weather["description"] as? String {
-                                        // アラートを表示
-                                        self.showAlert(message: description)
-                                    }
-                                }
-                            }
+                    let json = JSON(jsonResult)
+                    json["list"].forEach{(_, weathers) in
+                        weathers["weather"].forEach{(_, descriptions) in
+                            // アラートを表示
+                            self.showAlert(message: descriptions["description"].string!)
                         }
                     }
                 }

参考URL