id:nobuoka (@nobuoka)
株式会社はてな
2014-04-03 android.casual.test #2
はてなにおける
Android アプリのソフトウェアテスト
こんにちは、id:nobuoka です
● 普段の仕事
– サーバーサイド: Perl
– クライアントサイド: Web (JS)、Android アプリ (Java)
● 去年の 5 月ぐらいから Android アプリ開発を学び
始めた。
– 『Android アプリ開発のための Java 入門』
http://vividcode.hatenablog.com/entry/release-notes
/java-for-android-app-text
最近は Presso のサーバーサイド
是非ご利用ください!!
概要
● Android アプリ開発とソフトウェアテスト
● はてなでの Android アプリのテスト
● 細かなプラクティス
● カジュアルに情報共有。
● 他の組織でどういうテストをしてるのか知りたい。
Android アプリ開発と
ソフトウェアテスト
何のためのソフトウェアテストか
● 製品品質の向上
– 欠陥検出
– 欠陥の作りこみを防ぐ
– 設計の向上
– などなど
Android アプリ開発における
テストの重要性
● 多様な端末のサポート。
– API level、画面解像度、...。
● 動作確認しづらい状況をテストで実行する。
– 特殊な状況で期待通り動作するのか。
● 早期に欠陥を発見する。
– アプリとして完成してからではデバッグが困難。
– サーバー側が未完成という状況。
● 『テストのないコードはレガシーコードだ』
ソフトウェアテストだけが
品質向上の手段ではない
● コードレビュー、ベータテスト、などなど。
– 欠陥検出率、コストの面でソフトウェアテストより有利。
– 『CODE COMPLETE 第 2 版 下』
● テストを書くだけ無駄じゃないの? → NO
– コードレビュー等とは異なる種類の欠陥を検出。
– 設計向上等欠陥検出以外の効果、回帰テスト、など。
●
様々な手段を組み合わせよう。
– ソフトウェアテストもやろう!
はてなにおける
Android アプリのテスト
はてなのテスト文化
● もともとテストを書こうという文化がある。
– サーバーサイドはわりとしっかり書いてきた。
● 単体テスト、結合テスト。
● Jenkins での CI。
● Android アプリのテストはこれまでなかったが、導
入に際して特に障壁はなし。
– 当然、テスト導入のために上司を説得、とかはない。
Gradle + Android Gradle plugin
● ビルドやテスト実行が手軽にできる。
– ./gradlew connectedAndroidTest
● Ant や Maven を導入するよりも楽。
– Gradle wrapper の存在。
– Android Studio の標準ということ。
● IDE は Android Studio。
– Eclipse からまだ乗り換えられない、というチームでも
(Eclipse と併用で) Gradle を導入は有りだと思う。
Gradle + Android Gradle plugin
● まだ開発版で不安定なところもある。
– バグがあったり、API が変わったり。
– プラグインの中身を読める人間がいると安心。
● Eclipse と比べてビルドが遅い。
– より正確には実行ボタンを押してからが長い。
● 乗り換えられるなら乗り換えて良さそう。
● http://vividcode.hatenablog.com/entry/android-
app/gradle-build-system
Jenkins + Android Emulator plugin
● 定期的なテスト実行。
– リリース版パッケージを生成させるとかはしてない。
● Jenkins の設定画面上でプラグインのインストー
ル、エミュレータの設定など可能。
● プラグインが Android SDK をインストールし、ビル
ド時に Android エミュレータを起動してくれる。
● http://vividcode.hatenablog.com/entry/android-a
pp/jenkins-test
テストの導入は難しくない
● ビルドシステムに Gradle を使えばテスト実行は容
易。
● Android テスティングフレームワークの存在。
– Activity のテストや Service のテストのための
TestCase クラスが容易されている。
● Jenkins でテストを自動実行することも容易。
どういうテストを書いているか
● あらゆるテストを書いているわけではない。
– もともとテストはなかったわけだし。
● 主に単体テスト。
● いわゆるビジネスロジック部分。
● API level により分岐しているメソッドのテスト。
●
ネットワーク通信周り。
– 動作確認しづらいところ。 エラーレスポンス時とか。
●
などなど。
テストを書いて変更する
● テストを書くことでエンバグを防ぐ。
● 変更箇所の理解が深まる。
● 『レガシーコード改善ガイド』
●
バグ修正。
– まずはバグを再現するテストコードを記述。
– それからテストを変更し、実装も変更。
● 仕様変更やパフォーマンス向上等。
– バグ修正と同様、最初にテストを書いて、変更する。
Android アプリのソフトウェアテスト
にまつわるプラクティス
Android SDK のセットアップが面倒?
● Jenkins でテストを実行する際に面倒なのが
Android SDK の準備。
● ビルドスクリプト内で Android SDK の準備をする
Gradle plugin を使うと良い。
– nobuoka/vc-gradle-android-sdk-manager ← 作った
– cookpad/gradle-android-sdk-manager
– JakeWharton/sdk-manager-plugin
● CI だけでなく手元で開発する際にも便利。
Espresso (UI のテスト)
● android-test-kit に含まれる。
● UI 操作に関する単体テスト (?) をするなら
Espresso が手軽で良い。
– 複数 Activity にまたがる操作などは別のものを使っ
た方が良いだろう。
● ボタンクリックで期待通りの結果になるか、とか。
● バッドノウハウ: 古い API level (API level 8 で確認) だ
と、リストを一度スクロールしないと画面上にない
項目をタップできない。 (TouchUtils とかで。)
Espresso で UI のテストをする例
// 対象の `ListView`。
ListView listView =
(ListView) settingActivity.findViewById(android.R.id.list);
// バッドノウハウ: ドラッグしないと隠れてる項目をタップできない
TouchUtils.dragViewToTop(this, listView, 10);
// `keyValue` のキーを持つ項目をタップ。
Matcher<Preference> keyAdvancedMatcher =
PreferenceMatchers.withKey(keyValue);
onData(Matchers.<Object>allOf(keyAdvancedMatcher)).
perform(click());
● せっかくなのでデモでも。
GoogleInstrumentationTestRunner
● android-test-kit に含まれるテストランナー。
● Espresso を使用するなら必須。
● Espresso とは関係なく使用することも可能。
●
Instrumentation 終了前に、その instrumentation
で起動されたすべての activity が終了することを
保証する。
● Mockit を API level 7 以前で動くようにする。
Volley を使っているコードのテスト
● リクエスト、レスポンスの処理をモックしたい。
● Volley を使用している処理自体を置き換える。
● 別の方法: Volley ではネットワーク通信の処理が
抽象化されている (Network インターフェイス) の
で、テスト用の Network を作り、それを使う Volley
オブジェクトを使用する。
– com.android.volley.RequestQueueTest.OrderChecking
Network が参考になる。
テスト時のみ値を変えたい!
● 例えば接続先サーバーのホスト名を変えるとか。
● Build type の使用が 1 つの方法。
– Android Gradle plugin の機能。
● デフォルトの release、debug の他に testtarget
build を作り、テスト対象に設定。
● Testtarget build 用のリソースファイルを作成。
●
BuildConfig を使用するというのも。
テスト時のみ値を変えたい!
buildTypes {
/* テスト用のビルドタイプ */
testtarget.initWith(buildTypes.debug)
/* テスト時のみ BuildConfig.XXX_DRY_RUN を false にする */
release { buildConfigField "boolean", XXX_DRY_RUN "false" }
debug { buildConfigField "boolean", XXX_DRY_RUN, "false" }
testtarget { buildConfigField "boolean", XXX_DRY_RUN, "true" }
}
/* テスト用のビルドタイプを指定 */
testBuildType "testtarget"
● 使いすぎるのも良くないけど一つの方法として。
まとめ
● Gradle + Jenkins で Android アプリのテスト環境
の構築、テストの継続的な実行が容易。
● ソフトウェアテストを導入しよう!
– コスト的にためらっている? → 導入は容易
– 手動での動作確認やコードレビューなどと併用するこ
とで、より品質を高められる。
● android-test-kit など、テストのためのツールはい
ろいろある。
エンジニア募集!
Android アプリエンジニアも
そうじゃないエンジニアも
京都・東京
http://hatenacorp.jp/recruit/

はてなにおける Android アプリのソフトウェアテスト