XcodeにはXCTestというテストフレームワークが備わっています。
Defining Test Cases and Test Methods
XCTestを使ってアプリのテストコードを書いてみましょう
- 次のテストコードを書いてみましょう
- 天気予報が
sunny
だったら、画面に晴れ画像が表示されること - 天気予報が
cloudy
だったら、画面に曇り画像が表示されること - 天気予報が
rainy
だったら、画面に雨画像が表示されること - 天気予報の最高気温がUILabelに反映されること
- 天気予報の最低気温がUILabelに反映されること
- 天気予報が
- 余力があれば、JSONのエンコード、デコードのテストも書いてみましょう
テストコードを書く前提でプログラムの設計をしていないと、なかなかテストが書きづらいものです。
もし、テストコードが書けなかったら次の例のようにコードをリファクタリングしてみましょう。
※必ずこの通りにしなくてもOKです。最良の方法ではなく、シンプルな例の紹介です
WeatherFetching
というProtocolを定義するWeatherFetching
には天気予報を取得する関数を宣言するWeatherFetching
の実装クラスWeatherProvider
を定義する- ViewControllerから天気予報を取得する実装を切り離し、
WeatherProvider
におく - ViewControllerは
WeatherFetching
をプロパティとしてもつ - ViewControllerの天気予報を取得する実装を
WeatherFetching
の関数呼び出しに置き換える - 外部からViewControllerに
WeatherProvider
を渡す
テストでは任意の値を返すWeatherFetching
の実装クラスを用意しておき、
ViewControllerにそれを渡してあげるとテストコードが書きやすくなるでしょう。
Note
WeatherFetching
やWeatherProvider
は命名の一例です。
Swift API Design Guideline で Naming についてガイドラインが示されているので読んでみてください
SwiftにはProtocolという機能があります。
クラスを使わずに型を抽象的に扱うことができます。
上の例ですとViewControllerはWeatherFetching
に依存しています。
その依存先をProtocolで表現することで、テストの時は一定の値を返す実装に置き換えることができるようになります。
一方で、SwiftにはProtocol指向という考え方があります。
Protocol-Oriented Programming in Swift
サンプルコードが古いですが、日本語の分かり易い資料として
Swiftにおけるプロトコル指向プログラミング
SwiftとProtocol指向
IntやArrayなどの型もProtocolを用いて実装されています。
Conforms To
の項に採用されているProtocolが列挙されています。
このProtocolを辿っていくのも面白いです。
Int
Array
今回の課題ではProtocol指向としての設計には及んでいないように、筆者は思います。
Protocol指向についてここで詳細は述べませんが、ぜひ専門書など手にとってみてください。
DIや依存性の注入などと呼ばれます。
繰り返しますが、上の例ですとViewControllerはWeatherFetching
に依存しています。
例えば、ViewControllerがWeatherProvider
(実装クラス)を内部でインスタンス化したとすると...
せっかくProtocolで宣言したのに、実装クラスへの依存が生まれます。
しかし、外部から実装クラスを受け取るようにすると、ViewControllerはWeatherFetching
(Protocol)への依存しか持たず、その実装は意識しなくて良いことになります。
テストが書きやすくなったり、外部の変更に強いプログラムになり易いです。
任意の値を返す WeatherFetching
の実装クラスをいくつも用意するのは骨がおれます。
そういったモックやスタブの実装をサポートしてくれるライブラリがいくつかあります。
それがモックなのかスタブなのかについては以下の記事が詳しいです。