Robotium を使った
Android アプリ自動テスト
導入事例
2016/03/23 Android Testing Bootcamp#1
Sansan 株式会社 辰濱健一
Robotium を使った
Android アプリ自動テスト
導入事例
2016/03/23 Android Testing Bootcamp#1
Sansan 株式会社 辰濱健一
Sansan における
Android アプリ自動テスト
導入事例
2016/03/23 Android Testing Bootcamp#1
Sansan 株式会社 辰濱健一
Sansan における
Android アプリ自動テスト
導入事例
2016/03/23 Android Testing Bootcamp#1
Sansan 株式会社 辰濱健一
DroidKaigi RejectConf
の完コピの予定でしたが、
内容変更しました!!
Sansan における
Android アプリ自動テスト
導入事例
2016/03/23 Android Testing Bootcamp#1
Sansan 株式会社 辰濱健一
実は、既に自分の中では
Robotium オワコン…
> Agenda
5
• 自己紹介
• なぜ Robotium?
• テスト記述のポリシー
• 実行環境
• デモ
• 自動テストを導入してみて
• Appium で iOS とコードの共通化
• UI テストで他にもできそうなこと
• これから
自己紹介
6
> 自己紹介
7
• 辰濱健一 @tatsuhama50
• https://www.facebook.com/kenichi.tatsuhama
• http://www.slideshare.net/kenichitatsuhama
• 徳島県生まれ、徳島県勤務
• Tokushima.app というスマホアプリ勉強会を主催
• 趣味は音楽&旅行
> 自己紹介
8
• 業務経歴
• 1社目@徳島市
• Java, C++, MFC
• UWSC を使った Windows アプリの UI 自動テストの導入
• 性能改善チームにて、自動性能計測ツールを作成
• 2社目@徳島市
• iOS(Objective-C), Android(Java), Windows(C#)の
スマホ&タブレット向けアプリ開発
• 機能担当制、iOS で作った機能は作った人が他 OS に移植
• 3社目@徳島県神山町
• スマホアプリの自動テスト
• リモートワーク
開発&
品質担保と自動テスト
モバイル開発
モバイル開発での
品質担保と
自動テスト
> Sansan株式会社
9
モバイルアプリエンジニアは、2つの事業部で8人のメンバー
・Sansan … 4名(iOS x2 / Android x2)
・Eight … 4名(iOS x2 / Android x2)
- もう紙の名刺はいらない!
- 「超音波」等で周囲のEight
ユーザーを検索
- 複数のユーザー間でも名刺交
換ができる
- まずはアプリで+ボタンを!
10
> Eightの新機能「オンライン名刺交換」
11
> それでは
Eightのアプリを起動して、
「+」→「名刺交換」
→「近くのユーザと名刺交換」
画面をタッチ
で名刺交換してみましょう!
QRコードでもできるよ。
> Sansan神山ラボ
12
• 築70年の木造古民家(3棟)
• 略歴
• 2010年設置
• 〜2013/11:合宿所
• 2013/11〜:常駐メンバーのいる開発拠点に
• 家具家電、畑付き、風呂トイレセパレート
• 家賃:数万円 / 月
• インターネット接続:光回線
• 最寄り駅まで徒歩15分
• 改装OK物件
> Sansan神山ラボ
13
本題に入る前に…
14
> 本題に入る前に…
15
• UI テストは、ユニットテストに比べて、ものすごく時
間がかかります。
• コミット毎の UI テスト実施は現実的じゃないです
• デイリーやリリースごとがオススメ
• 本セッションは、UI テストのノウハウや弊社における
導入事例を紹介します
• 導入する費用対効果は、プロダクトによってまちまち
だと思うので各自で判断下さい
なぜ Robotium?
16
> スマホアプリの自動テストライブラリ
17
- Android 専用
- Robotium
- monkeyrunner
- Espresso
- UI Automater など…
- iOS 専用
- KIF
- Kiwi
- など…
- ハイブリッド
- Appium
- Calabash
- MonkeyTALK
- など…
> Robotium にした理由
18
• Android 実装と同じ Java 言語で記述
• アプリケーション内部のオブジェクトを参照できる
• UI に見えない内部の値、Activity の getter を呼べる
SharedPreference の値
• DB にもアクセスできるので期待値や操作を動的生成できる
→ サーバ DB 状態の変更にも強い
• ただし、リリースビルドでは使えない
• 導入当時(2014/05)、最終局面で Espresso とどっちにす
るか悩んだ。
•
> Robotium にした理由
19
• Android 実装と同じ Java 言語で記述
• アプリケーション内部のオブジェクトを参照できる
• UI に見えない内部の値、Activity の getter を呼べる
SharedPreference の値
• DB にもアクセスできるので期待値や操作を動的生成できる
→ サーバ DB 状態の変更にも強い
• ただし、リリースビルドでは使えない
• 導入当時(2014/05)、最終局面で Espresso とどっちにす
るか悩んだ。
• 今となっては、Espresso にしておけば良かったと思う…。
> Robotium にした理由
20
• Android 実装と同じ Java 言語で記述
• アプリケーション内部のオブジェクトを参照できる
• UI に見えない内部の値、Activity の getter を呼べる
SharedPreference の値
• DB にもアクセスできるので期待値や操作を動的生成できる
→ サーバ DB 状態の変更にも強い
• ただし、リリースビルドでは使えない
• 導入当時(2014/05)、最終局面で Espresso とどっちにす
るか悩んだ。
• 今となっては、Espresso にしておけば良かったと思う…。
• 判断当時メンテが最新の方を採った。Espresso の方が便利!
テスト記述のポリシー
21
> テスト記述のポリシー
22
• ライブラリとテストコードの結合度を下げる
• まずは、浅く・広く記述する
• あきらめも大事
• 待ち方のコツ
• どの環境でも動くように
テスト記述のポリシー
ライブラリとテストコードの結合度を下げる
23
> ライブラリとテストコードの結合度を下げる
24
• 目的
• テストコードの可読性を上げる
• ライブラリに依存しないテストコードにする
• ライブラリにない機能追加ができる
• 実行ログの記録
• エラー時にスクリーンショットを残すようにする
• 理由
• ライブラリの API 変更, ライブラリの置き換えでテスト
コードの修正が伴わない
• 失敗時の原因調査がしやすい
> Robotium Getting Started は密結合
25
• https://github.com/RobotiumTech/robotium/wiki/Getting-Started
• あくまでも API の使い方と思っておきましょう。
• 【対応】テストの基底クラスなどを作って clickOnText(String)を作り、
テストコードではそちらを呼び出す
テストコードと
ライブラリが密結合
> ライブラリの依存性排除
26
• ライブラリの隠蔽
Robotium 版
> ライブラリを置き換えるとしても…
27
• テストコードを修正することなく、対応可能
Robotium 版
Espresso 版
※Robotium と Espresso は同じ InstrumentationTest なので、共存可能!!
テスト記述のポリシー
まずは、広く・浅く記述する
28
> まずは、広く・浅く記述する
29
• 背景
• スマホアプリの UI や機能は比較的すぐ見直しが入る
• 使えないと致命的な機能と、そうでない機能がある
• 対策
• まずは、費用対効果の高い、主要機能のワンパスを通す
• ログイン → 検索・閲覧・編集 → ログアウト あたり
• ログイン時のバリデートチェックよりも、ログインできる
かの方が重要
• 慣れてきたら、各画面の詳細テストへ
テスト記述のポリシー
あきらめも大事
30
> あきらめも大事
31
• 別アプリと連携するものなどは手動で確認へ
• 例)
• カメラのピントが合っていること
• 住所文字列をタップすると地図アプリが起動し、その場所
にピンが立っていること
• URL をタップするとブラウザが起動し、ページが正しく表
示されること
• 場合によってはアプリ選択画面が出る
• 起動後の状態判定は目視の方が容易
• こういう所の自動化を頑張るのは費用対効果的に微妙…
> あきらめも大事
32
• 例)URL をタップするとブラウザが開く
アプリ ブラウザ
> あきらめも大事(だけど、知見共有)
33
• 例)URL をタップするとブラウザが開く
• Robotium や Espresso は UI 操作により別アプリが開
くと、その後どうしようもなくなる…
• 理由
• アプリケーションの操作であって、端末の操作ではない
• 対応策
• UI Automaterと 併用する
• ※但し、minSdkVersion に注意
• このあたりは、TOYAMA Sumio 氏の発表に委ねます
• Espresso の Intent チェックを使う
> あきらめも大事:メールチェック編
34
• 別アプリ…とはいえ、送られてきたメールをチェックする
なら、MailCatcher & MailCatcher API で実現可能
• MailCatcher
• SMTPサーバを経由したメールをブラウザから
確認できる。開発中の誤送信防止にも役立つ。
• http://mailcatcher.me/
• MailCatcher API
• /messages
• /messages/:id.json
• /messages/:id.html
• /messages/:id.plain
など
> あきらめも大事:メールチェック編
35
• Retrofit & RxAndroid を使えば容易
• 指定したタイトルのメールが届いているか?
• 特定のメールを開いて本文の URL をタップ
(メール本文から URL を抽出して、OkHttpClient など
で post する)
※Message モデルのプロパティは
一部しか宣言していない
テスト記述のポリシー
待ち方のコツ
36
> 待ち方のコツ
37
• テストコードでは SLEEP 関数は使わない
• 自作関数やライブラリのラッパー関数内で使うのはアリ
• 端末、実行環境、サーバの状態によって待ち時間は違
う!
• どうするか? → wait* 関数を使う
• ライブラリ関数の例
• waitForActivity
• waitForFragmentByTag
• waitForCondition
テスト記述のポリシー
どの環境でも動くように
38
> どの環境でも動くように
39
• 操作手順や期待値の動的生成
• エミュレータ判定
• 多言語対応
> どの環境でも動くように
40
• 操作手順や期待値の動的生成
• エミュレータ判定
• 多言語対応
> 操作手順や期待値の動的生成
41
• 弊社の開発事情によるところかも知れないですが…
「開発用」「ステージング」「本番」でデータセット
が異なります。
• 検索結果などが保証されるためにも
• ローカル DB を参照して操作手順や期待値を動的生成す
る
• ログイン後にテストコードでデータを作る操作を行う
• このデータに対し、検索・編集・削除などのテストを行う
• ノイズにならないためにログアウト前に作ったデータを
削除する操作を行う
• これにより、環境非依存なテストケースになります
> 操作手順や期待値の動的生成
42
実際のテストコード
myName : ”山田賢治”
users : {Uesr(阿部拓真), User(浅野緋美) ,
User(葉加瀬万太郎), …}
※ログインユーザを変えると、myName は違う値
※ログイン企業を変えると、users も違うデータセットが返る
> どの環境でも動くように
43
• 操作手順や期待値の動的生成
• エミュレータ判定
• 多言語対応
> どの環境でも動くように
44
• エミュレータかどうかの判定
• 実機じゃないと確認できない項目(カメラなど)は
このフラグを見てスキップさせる
> どの環境でも動くように
45
• 操作手順や期待値の動的生成
• エミュレータ判定
• 多言語対応
> 多言語対応
46
• https://github.com/RobotiumTech/robotium/wiki/Getting-Started
• ↑あくまでも API の使い方と思っておきましょう。
• 【対応】
• Robotium なら、clickOnText(@StringRes int) を作って、
getString(…)
• Espresso なら、withText に @StringRes int を渡す
日本語の時文言が違えば、
このコードはエラーになる
※表示文言が仕様通りであることの判定にはならないので要注意
実行環境
> 実行環境
48
• 基本的に実機で実行
• 昔は Jenkins & エミュレータでやっていた
• テストが増え、CI 環境を長時間(2h 以上※)占有する
&エミュレータが不安定なためやめた
• ※無料版、有料版など全パターン回した場合
• jacoco でカバレッジ計測
• どこのテストが足りてないかわかる
• 開発環境 DB で実施
• 固定のデータセット、特定のデータを使いたい場合は
Docker にて特定のデータセットを持つ DB を用意
> Jacoco のカバレッジレポート
49
• html で出力される(抜粋)
•
• 2016/02時点で 59% をカバーできている
> Jacoco のカバレッジレポート
50
• html で出力される
• 通っていないパスがよくわかる
> Docker を使った固定データ環境
51
• 開発環境(データや件数が他者によって書き換えられる可能性があ
る)でもテストが行えるようにしているが、以下のニーズ
がある
• パフォーマンス計測がしたい(ので、件数固定じゃないとダメ)
• テスト用に特定のユーザセットが欲しい
• 例)アカウント停止ユーザのエラーチェック
• アプリからは設定できないデータを持つ名刺が欲しい
• 例)名刺交換日未設定
• ローカル DB をアテにしない期待値を書きたい
• 例)山田賢治さんは○○枚名刺を持っている
• Docker で環境(API&DB)のイメージを持っておき、テス
トコードから環境準備&片付けを行う
> Docker を使った固定データ環境
52
• 事前準備
• Jenkins に環境起動用のジョブ / 環境破棄用のを作成
• テスト実行時
• setup() で 環境起動用の Jenkins ジョブを Jenkins WebAPI
を用いて実行
• アプリの API の向き先を差し替える
• テスト実行中
• 起動した環境に接続してテストを実施
• テスト終了時
• tearDown() で環境破棄用の Jenkins ジョブを Jenkins
WebAPI を用いて実行
• API の向き先を戻す
デモ
> デモ動画
54
• 2014/11 時点の動画です
• http://youtu.be/scY_RPgfxeY
• 4分ぐらいありますが、発表時間の都合上ちょっとだ
け…
自動テストを導入してみて
> 自動テスト導入してみて
56
• デグレードがないことを容易に確認できる
• メンテは思ったほど大変じゃない
• コツ:1行で書ける画面操作も clickSendButton() など
の関数にして共通利用するとよい
• テストでしっかりカバーしていれば、大規模なリファ
クタリングも安心!
• これから、通信ライブラリ・カメラ API・デザインパーツの差し替
え・DB の置き換え?などが控えている
• モックを使わないので、サーバの動作確認にもなる
• 同じ仕様の iOS アプリもテストしたい…
> 自動テスト導入してみて
57
• デグレードがないことを容易に確認できる
• メンテは思ったほど大変じゃない
• コツ:1行で書ける画面操作も clickSendButton() など
の関数にして共通利用するとよい
• テストでしっかりカバーしていれば、大規模なリファ
クタリングも安心!
• これから、通信ライブラリ・カメラ API・デザインパーツの差し替
え・DB の置き換え?などが控えている
• モックを使わないので、サーバの動作確認にもなる
• 同じ仕様の iOS アプリもテストしたい…
Appium で iOS アプリと
テストコードを共有する
> Appium
59
• http://appium.io/
• iOS アプリでも Android アプリでもテスト可能
• リリースバイナリでもテスト可能
• 但し、アプリ内部オブジェクトにはアクセスできない…
• Java, Ruby, JavaScript などで記述可能
> 設定ファイル(1/2)
60
> 設定ファイル(2/2)
61
> デモシナリオ
62
タップ 入力 エラー
> テストコード
63
iOS アプリの View の
アクセシビリティラベル
に Android と同様の
View ID を付与している
のがミソ
> 実行するコマンド
64
- Appium 起動
> appium &
- for iOS
> OS=iOS rspec spec/signup_spec.rb
- for Android
> OS=Android rspec spec/signup_spec.rb
- スクショ一覧作成(オレオレ Ruby ツール)
> cd screenshot
> ruby collector.rb
同じ!
デモ
> スクショ一覧(Android & iOS8)
66
> スクショ一覧(Android & iOS9)
67
iOS9だと、スクショで
一部 View が欠落する…
> Some elements are invisible on screenshot of iOS 9.2
68https://github.com/appium/appium/issues/6229
Appium の話は終わり。
Appium の話は終わり。
Appium 遅いね。。。
UI テストで他にもできそうなこと
(ちょっとだけ着手して、本格導入できていない件)
> 推移時間(イメージ)
72
• パフォーマンス改善の結果確認、性能デグレの検出が
できる(かも?)
• 通信状態やサーバ状態に大きく左右される気がする…
0
2
4
6
8
10
12
2015/2/27 2015/2/28 2015/3/1 2015/3/2 2015/3/3 2015/3/4 2015/3/5 2015/3/6
ログイン処理
初回同期
名刺画像送信
詳細データ取得
高画質画像データ取得
手動同期処理
> 通信回数の分析
73
- 呼び出し毎に API名と実行時間を csv ファイルに出力
- Excel のピボットテーブルで集計
- iOS / Android で同じ仕組みを入れれば、
同じ操作で API 呼び出しの違いがわかる!
そんなに呼び
出す必要ある
の…?
サーバ負荷削減のためのボトルネック分析が容易になる
Excelマクロ
> 通信回数の分析(推移)
74
- さっきのデータを実行毎に集計する
呼び出し回数削減施策導入
> スクショ一覧
75
画面名→
画面名→
画面名→
Nexus4 Nexus5 デザイン指示画像(期待値)
※元サイズが違うけど、
今は同じサイズで
表示されている
目で比較する!
デザイナのチェックや
意図しないレイアウト崩れの
確認が楽になりました
これから
> これから
77
• Espresso も併用して、Robotium ではテストしづら
かった部分のテスト(Intent のチェックなど)を行う
• UI Automater も併用して、
• アクティビティを保持しない設定にする
• 最小化&復帰後の画面状態のテスト
• AWS Device Farm を使って、所有していない端末
を時間借りしてテストを行う
• Device Farm も Appium をサポートしている!
※但し、まだ Java 記述のみ…
• http://www.slideshare.net/kenichitatsuhama/device-farm
まとめ
> まとめ
79
• 頑張ればいろいろできる
• 少人数でやっていれば影響範囲はわかるので、
導入は各自判断ください…
• 頑張りすぎない、広く浅くから!
• 色んな機種でスクリーンショット集めるのはオススメ
• 色んなライブラリを組み合わすことも可能
質疑応答
ステッカー欲しい方は
お声がけ下さい!!

Sansan における Android アプリ自動テスト導入事例

Editor's Notes

  • #12 先日発表したばかりのEightの新機能を紹介します。 名刺交換を、スマホだけでやってしまおう!というものです。 超音波やBluetooth、Wi-Fiなどを組み合わせた(Nearby API™)という技術を利用して、近くにいるEightユーザーを検出します。 複数のユーザー間でも一気にまとめて交換できるので、こうしたイベントで大勢の方々と名刺交換をするときに活躍します。
  • #13 ということで早速、いまアプリを立ち上げて、私と名刺交換してみましょう!