Ash Furrow
iOSエンジニアおよび著者としてArtsyで働くカナダ人です。多くのアプリを開発し、これまで4冊の書籍を出版しています。また、オープンソースのコントリビューターとしてコミュニティに関わっています。ブログでは、興味深いプログラミングのネタからフィルムカメラにまでおよぶ様々なトピックを扱っています。
Artyは4つのiOSアプリケーションを提供しています。すべてオープンソースとして公開しています。そしてすべて異なるアプローチを用いてテストされています。なぜでしょうか?それぞれ異なるテスト手法を用いることは、異なる環境においてうまく動くからです。ArtsyのiOSチームの判断の裏付けとなった議論や、どんな問題にあたり、どのように課題を解決したのかを紹介します。すばらしいソフトウェアを作るために、なぜテストが重要なのかをより理解できるようになるでしょう。
音楽と同じぐらい芸術を普及させたいと思っています。
4つのアプリを違うアプローチで単体テストしています
2つはObjective-CですがSwiftにも適用できます。
3つの概念を頭においてもらいたいと思います。100%のカバー率を目指さず、テストをするだけでも価値がある。
原稿コンポーネントを出来るだけ分割すべき
新しいアプリもコンポーネントをできるだけ小さくする、バカバカしいぐらいがいいと思います。
これが最初のもの。AppleTV用。いろんな都市の展覧会情報を見られる
テストの戦略は、ありませんでした
テストをすべきでない時がある、ということ、そして、皆さんにもしていない人、居ますよね?iOSのコミュニティでは新しい概念かもしれません、テストというのは。
時間が短かった、一人が隔離されて開発していた、ずっと。メンテナンスも最小限で新機能追加もなかった。目的が一つしかないシンプルなものでした。
テストをすべきかどうか
バランスが重要です。
同僚に作りなおしてと言っても2週間程度でしょう。ただその時はもっと短かったのです。
テストすべきか?そうです。でも必ずしもやらねばならないわけではないです。
2つめ
テストを後から追加した、画廊のアプリです。コードベースはさっきのよりもずっと大きく、壊れる可能性が高かったです。またAPI同期化する部分にバグを仕込んでは困るということで、テストをすることになりました。
何よりも重要なのはバスファクタ、個人に重要なバスが集中している、この人がバスに轢かれたら大変ということです。
個人が持っている知識を共有する必要があった。アプリがどのように動作するのか?
良いテストはアプリの外側の動きを表現します。
実はこのテストが良かったのはDI(依存性の注入)を使ったのが良かったです。
シングルトンではなく管理されたものでインジェクトします。インメモリコアデータをコンテキストのインメモリにおいておきます。テストをするオブジェクトに入れてオブジェクトがなにか処理をして、検査して予想通りに動いたか確認します。
概念的にはこのような形です。
RSpecスタイルのテストを使いました。共通処理を見出して切り出します。
更にリファクタリング
前処理でグループ化して入れ子になる。最初のテストスイートを見ると3つのテストが有ります。可読性がないです。
見やすいですね
どれだけコンテキストが有り、ネストされ複雑で、長さなのか、見て分かる。ネストがあまりにも深い場合はオブジェクトが複雑すぎる。
テストを追加すればドキュメントになります。テストは内部ではなく挙動をテストします。理想的には各クラスパブリックファンクションは一つにするべきです。DIはモックを活用するとよいです。RSpec系は完結で記述力の高いテストが出来てよいです。
アートのアプリ
急いで作って後でテストを加えた。コードがたくさんあって大勢の開発者が関わって買い方が違ってテストが大変。
そしてネットワーキング処理がアプリ中に散在していました。
3人でやっているのでやり方の違いがある。
またiPhoneだったアプリがユニバーサルに変わった。
SharedExampleをやった。テストを合格させるときにはiPhoneとiPadで見ていく。
もともとテストを追加するときには最大のクラスからテストしました。これが最も重かったのでプライオリティが高かったのでここからだと思った。でもこれをテストするには内部をテストしなくてはいけないことになり、内部実装を変えるとテストを沢山書き換えなくてはいけなくなった。
コードに変更を加えたら必ずテストをするようにしています。
私が好きなのはスナップショットのテストです。
ビューの写真を保存してPNGでレポジトリに保存していき、全く同じ設定で同じデータをレビューし、スナップショットを比較します。何か違ったらテストは不合格です。すごく便利です。ただリポジトリがすごく大きくなります。そう入ってお間違ってUIに変更を加えた時に検知しやすいです。PRを使ってレビューしている時も便利です、どう変化したかがわかりやすいです。PR見るのがわかりやすくなります。
どうしたらいいのか分からなくなったら他のエンジニアに生きます。
既存クラスを小さな要素にしてテストをしていくと楽にできます。始めたばかりのひとは小さなクラスからテストしてください。チームでルールを作り新しいコードはテストするようにし、最近の変更はテストしましょう。どうしていいかわからない時は効きましょう、iOSコミュニティは皆が助けてくれます。場合によってはよくないコードを描くこともある。そういう時はドキュメントを残し、どう治したいか残しましょう。
アートオークションアプリ
Enterpriseで、苦労をしたりしました。今でも技術的負債が残っています。
これが私たちの最初のSwiftアプリです。すべてが変わっていっていて、テストをすることで壊れないか確認することが出来まいた。 単体テストが唯一、最初のSwiftアプリケーションではわたしたちに慣れ親しんだものでした、Swiftの仕組みを理解することにも繋がりました。
QuickはRSpecスタイルのテストライブラリです。開発中にQuickを使い、開発中に質問を送ったりしました。Quickによって素晴らしいRspecスタイルのテストライブラリを手に入れました。ニンブルも。
良いテストは短いはずです。調整してアクションを取ってアサーションをとります。
アレンジメントはほとんどのメソッドの最初でやります。アサーションはテストするクラスの振る舞いが期待通りかチェックします。これをExoectationと呼びます。
ニンブルマッチャ−とは何でしょう?
シンプル!
ここまで出来る!!
ニンブルは等式用マッチャーだけではありません。ビルドインマッチャ−をストリング用にもArrayようにもRangeようにも有ります。
効果的テストは? * RspecStyle * 短いテストを描く * たくさんある
まとめ
- 完璧であろうとは思わない。理想的でないコードでも良い。ヘルプを求めましょう
- コンポーネントを小さくしましょう
- クラスを小さく、パブリックインターフェースは1つにしましょう。
- クラスの制約を書けることでテストしやすくなります。小さくすることで苦労を最低限に出来ます。
お話したアプリはGithubでご覧いただけます。
QA
テスト駆動好きだが、「重要だが、コストがかかる、サーバーサイドが完璧ならクライアントはいいのではないですか?」
Swiftは方が強力なのでテストは要らないというひとも居ます。コンパイルできたら実行できますから。でもコンパイルしたのに動かないということはよく有ります。アプリケーションの振る舞いを文章化出来る、クリティカルな部分が壊れないようにするとか、サーバーサイドと同じように重要だと私は思います。バグを入れたまま出荷するとAppStoreのレビューもありますし。
スナップショットテストとおっしゃっていましたが、UIテスト、結合テストはどのように位置づけていますか?
決めかねているとことがありますね。Xcodeのものもあり決めかねていますが、スナップショットが結構十分だと思っています。
初歩的な質問ですが、まだテストを書いていません。知り合いにTDDの初歩的なコーチングを受けましたが、テストを各時に試行の順序として、どのような機能をテストしたいか考えて、テストから先に書くという話をされた。普段の感覚で考えると実装から考えてしまい、単体の機能で考えるのが難しい。そこに良いアドバイスはあるか
TDD テスト駆動開発ですね 結構対立を生んだり色んな意見があり好きな人も嫌いな人も居る。私は中間に居ます。私はコードを書くのが好きですごく気が短いので実装を書くケースも有ります。分かっているけどやってしまいます。ただコードを書いて、クラスを書いて、テストが難しいというケースも出てくるのでそういう場合はクラスを変更します。それを繰り返すとテストが楽なクラスを書けるようになって来ます。そういった経験をしたから越しできることだと思うので、TDDと同じぐらいの価値があると思います。同じような堅牢性は無いかもしれませんが、十分だと思っています。
アドバイスは、クラスは小さめに。テストに苦労したら幾つかに分けて個々にテストし、DIを使って連携してテストできるか試してみてください。
テストが楽になる書き方ができるようになるっていうのがポイントね。 #tryswiftconf
— tora_dady (@ToraDady) 2016年3月4日
確かにTDD、いきなりテストから書くのは難しい。リファクタ的に使ってる。 #tryswiftconf
— 斉藤祐輔 (@uskwitter) 2016年3月4日
私もこれ派で、Quickとか使ってない。でも複雑さがパッと見分からないというのは確か。。 #tryswiftconf https://t.co/QMVyuJtqAT
— toshi0383 (@toshi0383) 2016年3月4日
https://twitter.com/takecian/status/705680263154528256Nimble だけつかうっていうのもあるのか #tryswiftconf
— 宇佐見 公輔 (@usamik26) 2016年3月4日
「アート系ECサイトArtsyのエンジニアが語る 素晴らしいアプリを作るためのテスト手法4つ #tryswiftconf」をトゥギャりました。 https://t.co/y29v193rwg
— トゥギャッター開発まとめ (@tg__dev) 2016年3月4日
気に入った記事は はてなブックマーク
はてなブックマークアプリiOS開発チームから来ました! はてなブックマークにはSwift特集があります! 良い記事を見逃さないように、ご利用ください! http://b.hatena.ne.jp/hotentry/it/Swift
そして良いまとめ記事があったらはてなブックマークでブックマークしましょう! try! Swift の記事で盛り上がると嬉しいです!