Slide 1

Slide 1 text

Androidテスティング実践 ③ユニットテスト・CI編

Slide 2

Slide 2 text

本スライドは、NTTソフトウェア社内技術者育成研修(ソフト道場研修)テキストです。 【著作権・免責事項】 !  本セミナーコースの内容、本資料のすべての著作権は、NTTソフトウェア株式会社に帰属します。 !  無断での本資料の複写、複製、再利⽤、転載、転⽤を禁じます。 !  本資料と演習等で利⽤するすべての教材は、NTTソフトウェア株式会社からの保証なしに提供されます。 !  本書に記載されている会社名および製品名は、⼀般に各社の商標または登録商標です。 Copyright © 2016, NTT Software Corporation. 120 ˞  演習問題に関するスライドは、⼀部を除き、本ファイルには含まれておりません。 また、演習に必要なソースコードも含まれておりません。ご了承ください。

Slide 3

Slide 3 text

3. ユニットテスト⾃動化 !  ユニットテストについて !  ツールの概要 !  ユニットテスト⾃動化で⼤事なこと !  プロダクトコードのテスト容易性 !  「レガシーコード」改善 121 Copyright © 2016, NTT Software Corporation.

Slide 4

Slide 4 text

Copyright © 2016, NTT Software Corporation. 122 ユニットテストについて

Slide 5

Slide 5 text

ユニットテストとは(1/2) ! 位置付け " 開発者が安⼼するためのテスト(Developer Test) " プロダクトがデグレしないようにするためのセーフティネット " 品質向上には寄与するが、品質保証が第⼀⽬的ではない ! 書くタイミング " プロダクトコードを書きながらテストも書く プロダクトコード完成後ではない ! テスト対象 " ビジネスロジック " 開発者が実装していて不安なところ " 画⾯(GUI)の試験は対象外とすることが多い 123 Copyright © 2016, NTT Software Corporation.

Slide 6

Slide 6 text

ユニットテストとは(2/2) テストを成功状態にしたままリファクタリングする テストを失敗から成功に変化させるようにテスト対象コードを書く テストを失敗させるテストコードを追加する テストを失敗から成功に変化させるようにテスト対象コードを書く 失敗するテストコードを書く Copyright © 2016, NTT Software Corporation. 124 ! (参考)TDD (テスト駆動開発)について http://www.atmarkit.co.jp/ait/articles/1403/05/news035.html

Slide 7

Slide 7 text

プロダクトコードの「テスト容易性」 テスト容易性=テストが書き易いプロダクトコード ! テストしたいロジックはActivityに書かない ! (匿名)内部クラス禁⽌ " リスナやAsyncTaskは普通のクラスにする。 必要なものはコンストラクタで受け取れば良い。 ! テスト⽤にフィールドを差し替えられるように " 「パッケージプライベート」なsetterやコンストラクタを 必要に応じて⽤意。 " テスト時にoverrideしたいメソッドをパッケージプライベートに。 " 「本来privateだがテストコードからはアクセスさせたいもの」は 「パッケージプライベート」で。 " テストはプロダクトと同じパッケージに置く。 Copyright © 2016, NTT Software Corporation. 125

Slide 8

Slide 8 text

「レガシーコード」改善 レガシーコード = テストが無いコード テストが無く仕様変更時に⼿がつけられないコード ! レガシーコード改善 " ⾃動ユニットテストでカバーしてから改造(変更)する " そのままだとテストが書けない場合 ! テストが書けるように、必要最低限の改造をする " デグレしないように、IDEのリファクタ機能を駆使する (⼿動で変更しない) " フィールド/メソッド/クラス追加やアクセス修飾⼦変更はOK ! 参考書籍「レガシーコード改善ガイド」 http://www.amazon.co.jp/dp/4798116831 126 Copyright © 2016, NTT Software Corporation.

Slide 9

Slide 9 text

Copyright © 2016, NTT Software Corporation. 127 ツールの概要 !  Robolectric !  Mockito

Slide 10

Slide 10 text

Robolectricの特徴 ! Android向けユニットテストフレームワーク http://robolectric.org/ " MIT License ! Androidフレームワークの動作をJVMでエミュレーション " APIレベル16から21をエミュレート可能(3.0版現在) " 実⾏速度が速い ! Mockitoとの併⽤が可能 ! 広い範囲のエミュレーションサポート " ビューの展開、リソース取得、データベース操作、etc. " とはいえ、JVM上のエミュレーションに過ぎないことに注意 128 ビジネスロジックの検証がメインとなる ユニットテストでは⼗分使える Copyright © 2016, NTT Software Corporation. ※http://robolectric.org/ よりロゴを引⽤

Slide 11

Slide 11 text

Robolectricのコンセプト ! ⾼速に実⾏できるLocal Unit Testの⽋点 (Android Framework APIが使えない) をRobolectricが克服 ! ユニットテスト・TDDで重要な 「開発のリズムを損わないサクサクさ」 でAndroid APIが絡んだ部分のテスト実⾏が可能になる 129 Copyright © 2016, NTT Software Corporation. local JVM (Java SE) テストコード JUnitなど Android Framework API (空実装→Robolectric) プロダクトコード

Slide 12

Slide 12 text

Robolectricの基本的な使い⽅(1/3) ! 基本はJUnit4 ! テストランナーを指定する(@RunWithアノテーション) ! テストの前提条件を指定する(@Configアノテーション) " constantsの指定は必須(Robolectricがgradleの情報を得るため) " その他、エミュレートしたいAPIレベルの指定なども可能。 http://robolectric.org/configuring/ 130 @RunWith(RobolectricGradleTestRunner.class) @Config(constants = BuildConfig.class) Copyright © 2016, NTT Software Corporation.

Slide 13

Slide 13 text

Robolectricの基本的な使い⽅(2/3) ! @RunWithと@Configをまとめて書くと ! @Configは設定ファイルに書いても良い(おすすめ!) " ファイル名: src/test/resources/robolectric.properties 131 @Config(constants = BuildConfig.class) @RunWith(RobolectricGradleTestRunner.class) public class MyFirstRobolectricTest { .... } constants=[パッケージ名].BuildConfig Copyright © 2016, NTT Software Corporation.

Slide 14

Slide 14 text

Robolectricの基本的な使い⽅(3/3) ! Shadowオブジェクト " AndroidフレームワークAPIの実装オブジェクト群 " Androidフレームワークが提供するクラスと1:1対応 ! Shadowオブジェクトの使いみち " Androidフレームワークでは提供されていないAPIを提供 " テストに有⽤な内部状態を知るためのAPIが中⼼ Copyright © 2016, NTT Software Corporation. 132 ImageView iv = (ImageView) activity.findViewById(.....); ShadowImageView shadow = Shadows.shadowOf(iv); ImageViewに対応するShadowオブジェクト ShadowImageView shadow = Shadows.shadowOf(iv); int resId = shadow.getImageResourceId(); 本来なら不可能な ImageViewの画像リソースIDにアクセス

Slide 15

Slide 15 text

Robolectricの制限事項(1/2) ! Robolectric本体の制限事項 " 3.0版:API Level 21 (Android 5.0)までサポート " 3.1版:API Level 23 (Android 6.0)までサポート ! targetSdkVersion=23では動作させるためには、 以下のいずれかの対応が必要 ※ https://github.com/robolectric/robolectric/issues/1932 参照 " robolectric.propertiesに「sdk=22」と追記する " build.gradleのdependenciesに、以下を追記する。 testCompile 'org.khronos:opengl-api:gl1.1-android-2.1_r1' ˞ compileSdkVersionとappcompat-v7のバージョンは 同じでなければならない点に注意! 133 Copyright © 2016, NTT Software Corporation.

Slide 16

Slide 16 text

Robolectricの制限事項(2/2) 134 Copyright © 2016, NTT Software Corporation. プロジェクトのbuild.gradleファイル // (省略) android { // (省略) compileSdkVersion 21 // (省略) defaultConfig { // (省略) targetSdkVersion 21 // (省略) } // (省略) } dependencies { compile 'com.android.support:appcompat-v7:21.+’ // (省略) } 新規PJ作成時は最新verになっているの でcompileSdkVersionに合わせて修正

Slide 17

Slide 17 text

Mockitoの紹介 特徴 " クラス定義から、そのクラスのスタブを⽣成できる " 実オブジェクトの⼀部メソッドの動作を変更できる " MIT License URL https://github.com/mockito/mockito (公式ホームページ) http://goo.gl/pOFyaQ (公式ドキュメント) http://tech.cm55.com/wiki/mockito/Manual (⽇本語紹介記事) 135 Copyright © 2016, NTT Software Corporation. ※https://github.com/mockito/mockito よりロゴを引⽤

Slide 18

Slide 18 text

mockの概念 136 Copyright © 2016, NTT Software Corporation. Hoge mockHoge = mock(Hoge.class); Hoge hoge = new Hoge(); 例えば で⽣成したmockHogeは と違い ! メソッドの戻り値を事前に定義したり ! メソッドが呼ばれた事を後から確認したり できる

Slide 19

Slide 19 text

spyの概念 137 Copyright © 2016, NTT Software Corporation. Hoge spyHoge = spy(new Hoge()); Hoge hoge = new Hoge(); 例えば で⽣成したspyHogeは と同じ実装を持ちつつ ! ⼀部のメソッドの戻り値を事前に定義したり ! メソッドが呼ばれた事を後から確認したり できる

Slide 20

Slide 20 text

Mockitoの使い⽅ ! 基本 " モックの作成(mock) " メソッドの振る舞い変更(when, thenReturn, thenThrow) " メソッドが呼び出されたことを確認(verify) ! 実オブジェクトの振る舞い変更 " spyオブジェクト⽣成(spy) " メソッドの振る舞い変更(doReturn, doNothing, doThrow) ! 公式ドキュメントのコード例参照 (1) Let's verify some behaviour! (2) How about some stubbing? (12) doReturn()|doThrow()| doAnswer()|doNothing()| doCallRealMethod() family of methods (13)Spying on real objects 138 Copyright © 2016, NTT Software Corporation.

Slide 21

Slide 21 text

Copyright © 2016, NTT Software Corporation. 139 【演習3-1】ユニットテスト環境構築 !  演習課題 !  ユニットテスト対応 !  Robolectricのテストサンプル作成 !  テスト実⾏

Slide 22

Slide 22 text

演習課題 ! 以下作業を通じて、テスト環境構築の⽅法を習得 してください。 " Android Studio上でアプリを新規作成する " ビルドスクリプトを修正してRobolectric + Mockito 対応にする " Robolectricのテストサンプルを追加し、実⾏してみる Copyright © 2016, NTT Software Corporation. 140

Slide 23

Slide 23 text

ユニットテスト対応(Gradle) 141 // (省略) dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) // (省略) testCompile 'junit:junit:4.12' testCompile 'org.hamcrest:hamcrest-library:1.3' testCompile 'org.robolectric:robolectric:3.0' testCompile 'org.mockito:mockito-core:1.10.19' // (省略) } (挿⼊)必要なライブラリの宣⾔ 詳細は別途提⽰ Copyright © 2016, NTT Software Corporation. Moduleのbuild.gradleファイル

Slide 24

Slide 24 text

Robolectricのテストサンプル作成(1/2) ! 以下のクラスを作成 (テスト対象クラス:EditActivity.javaのクラス名の上で Alt+Enter→Create Test) Copyright © 2016, NTT Software Corporation. 142 @RunWith(RobolectricGradleTestRunner.class) public class MyFirstRobolectricTest { private EditActivity activity; @Before public void setup() { activity = Robolectric.buildActivity(EditActivity.class).create().get(); } @Test public void testSomething() throws Exception { assertTrue(activity != null); } }

Slide 25

Slide 25 text

Robolectricのテストサンプル作成(2/2) !  robolectric.propertiesファイル作成 Copyright © 2016, NTT Software Corporation. 143 constants=[パッケージ名].BuildConfig

Slide 26

Slide 26 text

! コマンドラインからの実⾏ " Instrumented Testを実⾏する場合(端末を接続した状態で) " Local Unit Test(今回のRobolectric)を実⾏する場合 ! Android Studioからの実⾏ " テストしたいメソッドやクラスを選択して右クリック→[Run] (Ctrl+Shift+F10) ※Preferences→keymap→Run context configuration テスト実⾏ 144 gradlew connectedAndroidTest gradlew test Copyright © 2016, NTT Software Corporation. テストコードが緑に なっている

Slide 27

Slide 27 text

(参考)Mavenのプロキシ設定 プロキシ配下で利⽤する場合は以下の設定も必要 ! 以下のディレクトリにsettings.xmlを配置する " Windows系: c:\Users\ユーザー名\.m2\ ! settings.xmlの内容は以下の通り Copyright © 2016, NTT Software Corporation. 145 true http 【プロキシのホスト名】 【プロキシのポート番号】

Slide 28

Slide 28 text

! AndroidのHTTP通信ライブラリOkHttpのサブコンポー ネントとして配布 https://github.com/square/okhttp/tree/master/mockwebserver ! Apache License Version 2.0 ! セットアップ⽅法 " build.gradleのdependenciesブロックに以下を記述 ! サーバの開始⽅法 Copyright © 2016, NTT Software Corporation. 146 testCompile 'com.squareup.okhttp:mockwebserver:2.7.5' MockResponse response = ... (返して欲しいレスポンスを組み⽴てる) MockWebServer server = new MockWebServer(); server.enqueue(response); server.start(); URL mockServerUrl = server.url("/test").url(); URLのprefix(任意)を指定 (参考)MockWebServerについて(1/2)

Slide 29

Slide 29 text

(参考)MockWebServerについて(2/2) ! MockResponse(返して欲しいレスポンス)組み⽴て⽅法 ! MockWebServer終了の⽅法(tearDown()で呼び出す) ! プロキシ設定の無効化(MockServer開始前に呼び出す) 環境により不要な場合もあり。環境への依存を下げるため書いておくのがベター。 Copyright © 2016, NTT Software Corporation. 147 MockResponse response = new MockResponse() // JSONのContent-Type指定 .addHeader("Content-Type", "application/json; charset=utf-8") .setResponseCode(HTTPレスポンスコード) .setBody(HTTPレスポンスボディ); server.shutdown(); System.clearProperty("proxyHost"); System.clearProperty("proxyPort");

Slide 30

Slide 30 text

Copyright © 2016, NTT Software Corporation. 148 テスト対象アプリの解説

Slide 31

Slide 31 text

Copyright © 2016, NTT Software Corporation. 149 【演習3-2,3】ビジネスロジックのテスト

Slide 32

Slide 32 text

Copyright © 2016, NTT Software Corporation. 150 【演習3-4】イベントリスナのテスト

Slide 33

Slide 33 text

Copyright © 2016, NTT Software Corporation. 151 【演習3-5】 HTTP通信を伴うメソッドのテスト

Slide 34

Slide 34 text

Copyright © 2016, NTT Software Corporation. 152 【演習3-6】 データベースアクセスのテスト

Slide 35

Slide 35 text

4. CIの実現 !  CIの概要 !  Android開発プロジェクトに適⽤する !  (参考)Instrumented Testも実⾏する場合 Copyright © 2016, NTT Software Corporation. 153

Slide 36

Slide 36 text

CIとは ! 継続的インテグレーション(Continuous Integration) ! ⾃動的に以下を実施してくれる " リポジトリから最新のソースコード⼀式を取得 " ビルドや⾃動テストなど実⾏し、その結果を通知 Copyright © 2016, NTT Software Corporation. 154 通常は専⽤の サーバで動かす

Slide 37

Slide 37 text

CIのメリット ! ビルド・テストに失敗するコードがコミットされたとき に、いち早く検知し、対策を打つことができる。 ! Androidのように、ビルドや全テスト実⾏に時間がかかる 場合でも、CIサーバに全てお任せすれば、⽣産性向上に つながる。 Copyright © 2016, NTT Software Corporation. 155

Slide 38

Slide 38 text

Jenkins ! 概要 " 広く使われているCIサーバ https://jenkins.io/ " MIT License ! 特徴 " インストールが簡単 ! コマンドライン1⾏でOK (java -jar jenkins.war) ! yumやapt-getでインストールすることも可能 " 設定が簡単 ! 全てWeb画⾯から設定できる Copyright © 2016, NTT Software Corporation. 156 ※https://github.com/jenkinsci/jenkins よりロゴを引⽤

Slide 39

Slide 39 text

Android開発プロジェクトに適⽤する ! 前提条件 " Android StudioとGradleでプロジェクトが構築されていること " ソースコードがSubversionやGitで管理されており、 CIサーバからチェックアウトできること ! この研修で実現できる項⽬ " ビルド結果 " Android Lint結果 " Local Unit Test結果 ! この研修では概要のみ触れる項⽬ " Instrumented Test結果 (エミュレータの起動が不安定、実⾏時間が⾮常に⻑くなるなどの 問題があるため、導⼊には試⾏錯誤が必要) Copyright © 2016, NTT Software Corporation. 157

Slide 40

Slide 40 text

Android開発プロジェクトに適⽤する ! プラグインのインストール [Jenkinsの管理]→[プラグインの管理] " (★)Android Lint Plugin " Gradle plugin " Subversion plugin (ソースコードリポジトリがSubversionの場合) " Git plugin (ソースコードリポジトリがGitの場合) " JUnit plugin Copyright © 2016, NTT Software Corporation. 158 ˞ Jenkins 2.0からは、セットアップ時に「Suggested Plugins」を選択 していれば、★印のプラグインのみインストールすればOK

Slide 41

Slide 41 text

Android開発プロジェクトに適⽤する ! [Jenkinsの管理]→[システムの設定] ! [Jenkinsの管理]→[Global Tool Configuration] " 原則デフォルト設定のままでOK " 既にインストールされているJDKやgitなどを 利⽤したい場合はそのパスを指定しても良い。 Copyright © 2016, NTT Software Corporation. 159

Slide 42

Slide 42 text

Android開発プロジェクトに適⽤する ! 新規ジョブ作成 " 「フリースタイル・プロジェクトのビルド」を選択 " ソースコード管理 ! SubversionかGitを選択し、リポジトリのURLなどを⼊⼒ " ビルド・トリガ ! お好みで。迷ったら「SCMをポーリング」で良い " ビルド ! [ビルド⼿順の追加]→[Invoke Gradle script] ! [Use Gradle Wrapper]を選択 ! Tasksに[clean lint testDebugUnitTest]と⼊⼒ " ビルド後の処理 ! [ビルド後の処理の追加]→[Publish Android Lint results] ([Lint files]は空欄でOK) ! [ビルド後の処理の追加]→[JUnitテスト結果の集計] [テスト結果XML]に[app/build/test-results/debug/*.xml]と⼊⼒ Copyright © 2016, NTT Software Corporation. 160

Slide 43

Slide 43 text

(参考)Instrumented Testも実⾏する場合 ! [Jenkinsの管理]→[プラグインの管理] " Android Emulator Pluginをインストールする ! ジョブの設定 " [ビルド環境]→[Run an Android emulator during build]にチェック ! 起動したいエミュレータの情報を⼊⼒ ! [Common emulator options]→[Show emulator window]はチェックし ない " [Invoke Gradle script]→[Tasks] ! [connectedAndroidTest]を追加 " [ビルド後の処理]→[JUnitテスト結果の集計] ! [テスト結果XML]を[app/build/**/TEST*.xml]に修正 Copyright © 2016, NTT Software Corporation. 161

Slide 44

Slide 44 text

まとめ Copyright © 2016, NTT Software Corporation. 162

Slide 45

Slide 45 text

この研修で説明したこと ! ⾃動テストについての考え⽅ ! Androidのテストツール基礎知識 " Local Unit Test, Instrumented Test, ATSL, ... ! システムテスト⾃動化ツールの使い⽅ " Robotium, Espresso, UI Automator, Appium ! ユニットテスト⾃動化ツールの使い⽅ ! 各種テストは以下のテクニックを駆使して実現する " Android Studioのリファクタリング機能 " テスト⽤のメソッド・コンストラクタの追加 " Mockitoのmock()とspy() " MockWebServer ! CIの実現⽅法 Copyright © 2016, NTT Software Corporation. 163

Slide 46

Slide 46 text

最後に ! プロダクトコードを⾃動化したユニットテストで カバーすることで、ソース修正時の安⼼感が劇的に上がります。 ! 既にレガシーコードがある場合は、全部やろうとせず、 CIやユニットテストから少しずつ始めて⾏くと良いでしょう。 " テストが全く無くても、CIだけ始めてみる。 ! Android Studioに移⾏するだけで始められます。 " 新しく機能追加したところだけでもテストを書いてみる。 ! リリースを何度も⾏うプロジェクトでは、 システムテスト⾃動化にもチャレンジしてみてください。 Copyright © 2016, NTT Software Corporation. 164

Slide 47

Slide 47 text

おわり お疲れ様でした

Slide 48

Slide 48 text

https://www.ntts.co.jp/products/soft_dojyo/index.html