テスト書け書けおじさん in DroidKaigi 2016
こんにちは! テスト書け書けおじさんこと、Androidエンジニアの海藤です。
おじさんと名乗っていますが、2015年の新卒として入社しているので、気分的にはテスト書け書けお兄さんといった感じです。
私の発表はAndroidのテスト自動化に関するもので、ここ数ヶ月業務で取り組んでいた課題でもあります。この記事では、発表で伝えきれなかった行間の補足と、質疑応答やTwitterでいただいた質問のうちで回答しきれなかった部分に回答していきたいと思います。
発表内容
概要
Android界隈では、Testing Support Libraryとしてテストフレームワークがリリースされたこともあり、ちゃんとテストを書こうという流れがあります。しかし、今までテストを書いてこなかったプロジェクトにいきなりテストを書こうとしてもうまくいかないことが多いのではないでしょうか? 実際に私が担当しているCouplesでもテストを導入しようとしてうまくいきませんでした。このような状況に直面した私がテスト書け書けおじさんにジョブチェンジした経緯と、その過程でどんなことをしたのかということを発表しました。
テストがないとどう辛いのか
CouplesではGoogle Spreadsheetでテストケースを管理しており、リリース前に影響のあるテストケースを人力で確認していました。この人力確認がすでに辛い作業であることはエンジニアの方であればお分かりいただけるかと思いますが、人力であるが故にヒューマンリソースを考慮すると毎回全部を確認するわけにはいかず、影響範囲を考慮した上で関連のあるテストケースを確認することになります。
Android版はiOS版のリリース後から開発に着手しており、当時はとにかく早くリリースすることを重視していました。このような状況で開発されたAndroid版は基盤実装に無理があり、修正箇所とはまったく関係のない部分がエラーになってしまうこともありました。この状態においては先に述べたテストケースの人力確認でバグを見つけるという運用は限界に近づきつつあると感じたのが、テスト書け書けおじさんが誕生したきっかけです。
Couplesの設計
Android版は大きく分けて以下の2つの問題を抱えていました。
- マッチョなActivity/Fragment
- 複雑な依存関係を持った基盤実装
AndroidではActivity/FragmentがMVCにおけるView、Controllerという2つの性質を持ってしまっているが故にコード量の多いマッチョなActivity/Fragmentになりがちです。また、基盤実装に関してもとにかく早くリリースすることを重視して複数人で同時開発したため、統一感がなく複雑な依存関係を持ってしまっている状態でした。
Couplesはユーザーからの要望を出来る限り実現するためにUIを頻繁に変更しています。そこで、まずは変更の少ないバックエンドから攻めるという方針を決めました。バックエンドを攻める際の選択肢としては以下の2つが考えられます。
- 既存のバックエンドに直接手を入れる
- 新しいバックエンドを開発して順次乗り換える
※ ここでのバックエンドはあくまでDBやAPI経由でのデータ取得といったAndroidアプリ内でのバックエンドを指します
1つ目の方法はそもそもテストがない状態で手を入れてしまうとアプリ全体に影響が及んでしまうため、テストを書いてリスクを抑えつつ、順次乗り換えが可能な2つ目の方法を選択しました。
テスタビリティの高い設計
新たなバックエンドを実装するにあたって、テスタビリティの高い設計にするべく、以下の2点に注意して設計を行いました。
- 各層の役割が明確
- CIサーバー上で継続的なテストが可能
まずは、バックエンドの各処理を適切にモジュール化して、各層の役割を明確にすることでそもそもテストが書ける状態にします。それと平行してCIサーバー上で継続的にテスト可能な状態を作ることでテストが形骸化することを防止しています。
上記の2点を考慮して以下のような設計にしました。
上記の設計では主に、DBからのデータ取得を担当するDatabase、APIからのデータ取得を担当するNetwork、それら2つのデータソースからのデータを統括するRepositoryという3つに分かれています。この3つはそれぞれの役割が明確化されており、その役割を満たしているかというテストを書くことで品質を担保することが出来ます。また、この3つはAndroidフレームワークに依存していないため、CIサーバー上で容易にテストを実行することが可能になります。Androidのテストにそれほど詳しくない方向けに補足すると、Androidフレームワークへの依存がある状態だとCIサーバーでテストを実行するために一手間必要になります。
サンプルアプリでのテスト
前章で紹介した設計で実装したサンプルアプリのテストコードを紹介しました。
記事内でコードを紹介すると長くなってしまうため、コードを見たい方はこちらをご覧ください。
テストを書く文化を作るために
Android版は総勢10名のエンジニアで開発しています。内訳としては、社員3名、業務委託4名、インターン3名です。ネイティブアプリ開発のチームとしては他社では類を見ないほど大規模なチームではないかなと思います。10名もエンジニアがいるとそれぞれの技術レベルは様々で、さらに全員テストを書いたことがないという状況でした。この状況では、テストが書ける環境を作っただけでは結局誰もテストを書かないだろうなということが容易に想像できます。そんな中でチーム全員がテストを書くという文化を作るために、週1で以下のような勉強会を開催して徐々にテストに慣れてもらうということをやりました。
- 新しいバックエンド設計について
- 一般的なソフトウェアテストについて
- Androidでのテストについて
- テストを書く際のTips
質問
ここからは質疑応答のタイミングやTwitterでいただいた質問に回答していきたいと思います。
現在どのくらいのテストを書いているんですか?
現在は新しいバックエンドの実装が完了し、アプリ内で比較的重要度の低い部分を新しいものに置き換えて、それに対するテストを書いたという状態です。全体での割合で言うとまだ5%といったところです。
他のメンバーはテストを書くようになったんですか?
結論から言えば、まだ他のメンバーはテストを書いていません。弊社ではプルリクエストを使ったコードレビューを行っており、今回実装した新しいバックエンドは現在レビュー中でまだ本線にマージされていないという状態です。テストはこの新しいバックエンドの乗り換えるタイミングで書くことを想定しているため、他のメンバーがテストを書くのは今回の変更が本線にマージされた後ということになります。
テストを書く工数をどうやって上から貰ったんですか?
弊社はエンジニアが全社員の50%以上を占めており、経営陣やマネージャー陣がエンジニアリングはもとより、テストのメリットを十分に理解しているため、工数をもらうために大げさな説得が必要だったということはありませんでした。もちろん、Android版の現状とテストを書くことによるリターンを説明した上で承認はもらっています。
フロントエンドのテストは書かないんですか?
Couplesはユーザーからの要望を実現するためにUIを頻繁に変更しています。そういった状況ではフロントエンドのテストを書いたとしても無駄になってしまうことがあるため、現状はフロントエンドのテストは書いていません。しかし、バックエンドを整理したことによってフロントエンドも綺麗に整理されつつあるので、フロントエンドの中でも重要度の高い部分に関してはテストを書いていく方針です。
Espresso以外のUIテストフレームワークは使わないんですか?
現状はバックエンドのテストに比重を置いているため、スライドではEspressoのみを紹介しましたが、CalabashやAppiumといった他のUIテストフレームワークも導入を検討中です。
さいごに
去年は一般枠での参加でしたが、今年は思い切って登壇枠で参加しました。結果として、登壇したことで様々な方から質問やフィードバックをいただき、それをCouplesにも還元することが出来ました。Androidアプリ開発に必要な知識は非常に多く、一人では到底カバーしきれませんが、こういったイベントで様々な方が様々な情報を共有してくれることでAndroid界隈全体の活性化にも繋がっているなと感じます。今後も個人としてもエウレカとしても業界の活性化に少しでも協力していきたいと思います。