androidテスティング実践3 ユニットテスト・ci編

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

Upload: -ntt

Post on 22-Jan-2018

1.979 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: Androidテスティング実践3 ユニットテスト・CI編

Androidテスティング実践

③ユニットテスト・CI編

Page 2: Androidテスティング実践3 ユニットテスト・CI編

本スライドは、NTTソフトウェア社内技術者育成研修(ソフト道場研修)テキストです。

【著作権・免責事項】

本セミナーコースの内容、本資料のすべての著作権は、NTTソフトウェア株式会社に帰属します。

無断での本資料の複写、複製、再利用、転載、転用を禁じます。

本資料と演習等で利用するすべての教材は、NTTソフトウェア株式会社からの保証なしに提供されます。

本書に記載されている会社名および製品名は、一般に各社の商標または登録商標です。

Copyright © 2016, NTT Software Corporation. 120

※ 演習問題に関するスライドは、一部を除き、本ファイルには含まれておりません。また、演習に必要なソースコードも含まれておりません。ご了承ください。

Page 3: Androidテスティング実践3 ユニットテスト・CI編

3. ユニットテスト自動化 ユニットテストについて

ツールの概要

ユニットテスト自動化で大事なこと

プロダクトコードのテスト容易性

「レガシーコード」改善

121Copyright © 2016, NTT Software Corporation.

Page 4: Androidテスティング実践3 ユニットテスト・CI編

Copyright © 2016, NTT Software Corporation. 122

ユニットテストについて

Page 5: Androidテスティング実践3 ユニットテスト・CI編

ユニットテストとは(1/2)

位置付け

開発者が安心するためのテスト(Developer Test)

プロダクトがデグレしないようにするためのセーフティネット

品質向上には寄与するが、品質保証が第一目的ではない

書くタイミング

プロダクトコードを書きながらテストも書くプロダクトコード完成後ではない

テスト対象

ビジネスロジック

開発者が実装していて不安なところ

画面(GUI)の試験は対象外とすることが多い

123Copyright © 2016, NTT Software Corporation.

Page 6: Androidテスティング実践3 ユニットテスト・CI編

ユニットテストとは(2/2)

テストを成功状態にしたままリファクタリングする

テストを失敗から成功に変化させるようにテスト対象コードを書く

テストを失敗させるテストコードを追加する

テストを失敗から成功に変化させるようにテスト対象コードを書く

失敗するテストコードを書く

Copyright © 2016, NTT Software Corporation. 124

(参考)TDD (テスト駆動開発)についてhttp://www.atmarkit.co.jp/ait/articles/1403/05/news035.html

Page 7: Androidテスティング実践3 ユニットテスト・CI編

プロダクトコードの「テスト容易性」

テスト容易性=テストが書き易いプロダクトコード

テストしたいロジックはActivityに書かない

(匿名)内部クラス禁止

リスナやAsyncTaskは普通のクラスにする。必要なものはコンストラクタで受け取れば良い。

テスト用にフィールドを差し替えられるように

「パッケージプライベート」なsetterやコンストラクタを必要に応じて用意。

テスト時にoverrideしたいメソッドをパッケージプライベートに。

「本来privateだがテストコードからはアクセスさせたいもの」は「パッケージプライベート」で。

テストはプロダクトと同じパッケージに置く。

Copyright © 2016, NTT Software Corporation. 125

Page 8: Androidテスティング実践3 ユニットテスト・CI編

「レガシーコード」改善

レガシーコード = テストが無いコードテストが無く仕様変更時に手がつけられないコード

レガシーコード改善自動ユニットテストでカバーしてから改造(変更)する

そのままだとテストが書けない場合テストが書けるように、必要最低限の改造をするデグレしないように、IDEのリファクタ機能を駆使する

(手動で変更しない)

フィールド/メソッド/クラス追加やアクセス修飾子変更はOK

参考書籍「レガシーコード改善ガイド」http://www.amazon.co.jp/dp/4798116831

126Copyright © 2016, NTT Software Corporation.

Page 9: Androidテスティング実践3 ユニットテスト・CI編

Copyright © 2016, NTT Software Corporation. 127

ツールの概要 Robolectric

Mockito

Page 10: Androidテスティング実践3 ユニットテスト・CI編

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/ よりロゴを引用

Page 11: Androidテスティング実践3 ユニットテスト・CI編

Robolectricのコンセプト

高速に実行できるLocal Unit Testの欠点(Android Framework APIが使えない)をRobolectricが克服

ユニットテスト・TDDで重要な「開発のリズムを損わないサクサクさ」でAndroid APIが絡んだ部分のテスト実行が可能になる

129Copyright © 2016, NTT Software Corporation.

local JVM (Java SE)

テストコード

JUnitなどAndroid Framework API

(空実装→Robolectric)

プロダクトコード

Page 12: Androidテスティング実践3 ユニットテスト・CI編

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.

Page 13: Androidテスティング実践3 ユニットテスト・CI編

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.

Page 14: Androidテスティング実践3 ユニットテスト・CI編

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にアクセス

Page 15: Androidテスティング実践3 ユニットテスト・CI編

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のバージョンは同じでなければならない点に注意!

133Copyright © 2016, NTT Software Corporation.

Page 16: Androidテスティング実践3 ユニットテスト・CI編

Robolectricの制限事項(2/2)

134Copyright © 2016, NTT Software Corporation.

プロジェクトのbuild.gradleファイル

// (省略)

android {

// (省略)

compileSdkVersion 21

// (省略)

defaultConfig {

// (省略)

targetSdkVersion 21

// (省略)

}

// (省略)

}

dependencies {

compile 'com.android.support:appcompat-v7:21.

// (省略)

}

新規PJ作成時は最新verになっているのでcompileSdkVersionに合わせて修正

Page 17: Androidテスティング実践3 ユニットテスト・CI編

Mockitoの紹介

特徴

クラス定義から、そのクラスのスタブを生成できる

実オブジェクトの一部メソッドの動作を変更できる

MIT License

URLhttps://github.com/mockito/mockito (公式ホームページ)

http://goo.gl/pOFyaQ (公式ドキュメント)

http://tech.cm55.com/wiki/mockito/Manual (日本語紹介記事)

135Copyright © 2016, NTT Software Corporation.

※https://github.com/mockito/mockito よりロゴを引用

Page 18: Androidテスティング実践3 ユニットテスト・CI編

mockの概念

136Copyright © 2016, NTT Software Corporation.

Hoge mockHoge = mock(Hoge.class);

Hoge hoge = new Hoge();

例えば

で生成したmockHogeは

と違い

メソッドの戻り値を事前に定義したり

メソッドが呼ばれた事を後から確認したり

できる

Page 19: Androidテスティング実践3 ユニットテスト・CI編

spyの概念

137Copyright © 2016, NTT Software Corporation.

Hoge spyHoge = spy(new Hoge());

Hoge hoge = new Hoge();

例えば

で生成したspyHogeは

と同じ実装を持ちつつ

一部のメソッドの戻り値を事前に定義したり

メソッドが呼ばれた事を後から確認したり

できる

Page 20: Androidテスティング実践3 ユニットテスト・CI編

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

138Copyright © 2016, NTT Software Corporation.

Page 21: Androidテスティング実践3 ユニットテスト・CI編

Copyright © 2016, NTT Software Corporation. 139

【演習3-1】ユニットテスト環境構築 演習課題

ユニットテスト対応

Robolectricのテストサンプル作成

テスト実行

Page 22: Androidテスティング実践3 ユニットテスト・CI編

演習課題

以下作業を通じて、テスト環境構築の方法を習得してください。

Android Studio上でアプリを新規作成する

ビルドスクリプトを修正してRobolectric + Mockito対応にする

Robolectricのテストサンプルを追加し、実行してみる

Copyright © 2016, NTT Software Corporation. 140

Page 23: Androidテスティング実践3 ユニットテスト・CI編

ユニットテスト対応(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ファイル

Page 24: Androidテスティング実践3 ユニットテスト・CI編

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);

}

}

Page 25: Androidテスティング実践3 ユニットテスト・CI編

Robolectricのテストサンプル作成(2/2)

robolectric.propertiesファイル作成

Copyright © 2016, NTT Software Corporation. 143

constants=[パッケージ名].BuildConfig

Page 26: Androidテスティング実践3 ユニットテスト・CI編

コマンドラインからの実行

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.

テストコードが緑になっている

Page 27: Androidテスティング実践3 ユニットテスト・CI編

(参考)Mavenのプロキシ設定

プロキシ配下で利用する場合は以下の設定も必要以下のディレクトリにsettings.xmlを配置するWindows系: c:¥Users¥ユーザー名¥.m2¥

settings.xmlの内容は以下の通り

Copyright © 2016, NTT Software Corporation. 145

<?xml version="1.0" encoding="UTF-8"?><settings>

<proxies>

<proxy>

<active>true</active>

<protocol>http</protocol>

<host>【プロキシのホスト名】</host>

<port>【プロキシのポート番号】</port>

</proxy>

</proxies>

</settings>

Page 28: Androidテスティング実践3 ユニットテスト・CI編

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)

Page 29: Androidテスティング実践3 ユニットテスト・CI編

(参考)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");

Page 30: Androidテスティング実践3 ユニットテスト・CI編

Copyright © 2016, NTT Software Corporation. 148

テスト対象アプリの解説

Page 31: Androidテスティング実践3 ユニットテスト・CI編

Copyright © 2016, NTT Software Corporation. 149

【演習3-2,3】ビジネスロジックのテスト

Page 32: Androidテスティング実践3 ユニットテスト・CI編

Copyright © 2016, NTT Software Corporation. 150

【演習3-4】イベントリスナのテスト

Page 33: Androidテスティング実践3 ユニットテスト・CI編

Copyright © 2016, NTT Software Corporation. 151

【演習3-5】HTTP通信を伴うメソッドのテスト

Page 34: Androidテスティング実践3 ユニットテスト・CI編

Copyright © 2016, NTT Software Corporation. 152

【演習3-6】データベースアクセスのテスト

Page 35: Androidテスティング実践3 ユニットテスト・CI編

4. CIの実現 CIの概要

Android開発プロジェクトに適用する

(参考)Instrumented Testも実行する場合

Copyright © 2016, NTT Software Corporation. 153

Page 36: Androidテスティング実践3 ユニットテスト・CI編

CIとは

継続的インテグレーション(Continuous Integration)

自動的に以下を実施してくれる

リポジトリから最新のソースコード一式を取得

ビルドや自動テストなど実行し、その結果を通知

Copyright © 2016, NTT Software Corporation. 154

通常は専用のサーバで動かす

Page 37: Androidテスティング実践3 ユニットテスト・CI編

CIのメリット

ビルド・テストに失敗するコードがコミットされたときに、いち早く検知し、対策を打つことができる。

Androidのように、ビルドや全テスト実行に時間がかかる場合でも、CIサーバに全てお任せすれば、生産性向上につながる。

Copyright © 2016, NTT Software Corporation. 155

Page 38: Androidテスティング実践3 ユニットテスト・CI編

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 よりロゴを引用

Page 39: Androidテスティング実践3 ユニットテスト・CI編

Android開発プロジェクトに適用する

前提条件

Android StudioとGradleでプロジェクトが構築されていること

ソースコードがSubversionやGitで管理されており、CIサーバからチェックアウトできること

この研修で実現できる項目

ビルド結果

Android Lint結果

Local Unit Test結果

この研修では概要のみ触れる項目

Instrumented Test結果(エミュレータの起動が不安定、実行時間が非常に長くなるなどの問題があるため、導入には試行錯誤が必要)

Copyright © 2016, NTT Software Corporation. 157

Page 40: Androidテスティング実践3 ユニットテスト・CI編

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

Page 41: Androidテスティング実践3 ユニットテスト・CI編

Android開発プロジェクトに適用する

[Jenkinsの管理]→[システムの設定]

[Jenkinsの管理]→[Global Tool Configuration]

原則デフォルト設定のままでOK

既にインストールされているJDKやgitなどを利用したい場合はそのパスを指定しても良い。

Copyright © 2016, NTT Software Corporation. 159

Page 42: Androidテスティング実践3 ユニットテスト・CI編

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

Page 43: Androidテスティング実践3 ユニットテスト・CI編

(参考)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

Page 44: Androidテスティング実践3 ユニットテスト・CI編

まとめ

Copyright © 2016, NTT Software Corporation. 162

Page 45: Androidテスティング実践3 ユニットテスト・CI編

この研修で説明したこと

自動テストについての考え方

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

Page 46: Androidテスティング実践3 ユニットテスト・CI編

最後に

プロダクトコードを自動化したユニットテストでカバーすることで、ソース修正時の安心感が劇的に上がります。

既にレガシーコードがある場合は、全部やろうとせず、CIやユニットテストから少しずつ始めて行くと良いでしょう。

テストが全く無くても、CIだけ始めてみる。

Android Studioに移行するだけで始められます。

新しく機能追加したところだけでもテストを書いてみる。

リリースを何度も行うプロジェクトでは、システムテスト自動化にもチャレンジしてみてください。

Copyright © 2016, NTT Software Corporation. 164

Page 47: Androidテスティング実践3 ユニットテスト・CI編

おわりお疲れ様でした

Page 48: Androidテスティング実践3 ユニットテスト・CI編

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