AndroidをテストするためのJUnit4入門


Testing Support Libraryの概要と、それを理解する上で必要なJUnit4の説明が主になります。
AndroidとJUnit4まわりを多少でも理解する助けになればと思います。

[前回](http://qiita.com/hymmr/items/48bc745cdd31b79c4aeb) InstrumentationTestのGoogleのサンプルがJUnit3かつTesting Support Libraryを使ってないので古いことに気づきました。。。テストの感覚を理解するのには良かった気がしますが、やはり新しいのを使っていきたいところです。

#Android Testing Support Library概要
AndroidのアプリをテストするためのGoogle公式のライブラリです。
JUnit4が使えて(JUnit3も使える)、UIテストや、Androidのためのテストランナーがあります。
主な機能は以下のとおりです。

- AndroidJUnitRunner
    - JUnit4が使えるAndroid用テストランナー
    - Android2.2(API8)から使える
- Espresso
    - UIのテストフレームワーク
    - 簡単に記述できる
    - Android2.2(API8)から使える
- UIAutomater
    - UIのテストフレームワーク 
    - 他のアプリとの連携などアプリ間テストに適している
    - Android4.3(API18)から使える

##AndroidJUnitRunner

- JUnit4が使える
- APIレベル1から入ってるInstrumentationTestRunnerの置き換え
- デバイスのみ実行やテストの大きさでフィルターできる

#JUnit4
Javaのデファクトスタンダードのテスティングフレームワーク
実行、検証API、テストケースフォーマットなど
アノテーションを使うことによってテスト実行の流れと記述が分かりやすい(JUnit3以前は命名規則を使った記述、アノテーションが使えない)

##用語的なもの
- テストケース
    - 1つのテスト項目
- テストスイート
    - いくつかのテストケースをまとめたもの
- アサーション
    - 比較検証
    - テスト結果である実測値が期待値と一致する
- Macher API
    - 様々な比較するメソッド群
    - アサーションの中で使う
- テストランナー
    - テストを実行する
    - 詳しくは後ほど
- テストダブル
    - 依存するオブジェクトの代役
    - スタブ
        - 借りのクラスやモジュール
        - 依存のない振る舞いをさせる
    - モック
        - スタブと似ている
        - メソッドがテストで呼ぶ出されたかを検証


##代表的なJUnit4のアノテーション
- ```@Test```
    - テストメソッドの宣言
    - 引数を保たないpublicメソッドにする
    - ```@Test(expected=Exception.class)```で例外がでるテスト
- ```@Before```
    - 初期化 テスト実行前の処理
    - 引数を保たないpublicメソッドにする
    - setUpってメソッド名にするのが普通
- ```@After```
    - 後処理
    - 引数を保たないpublicメソッドにする
    - 必ず行わなければならない後処理
    - tearDownってメソッド名にするのが普通
- ```@Ingnore```
    - テスト実行除外
    - 一時的に実行したくない時に使う

##テストランナー
- テストを実行する
- どのようにテストするかカスタマイズできる(すべてのクラス、特定のクラスだけ、特定のクラスだけ除いてなど)
- テストクラスに```@RunWith()```を付与してテストランナークラスを指定する
- 書かない場合はJunit4クラスが適応される

###テストランナークラス
テストランナーの振る舞いをテストランナークラスで変える事ができる
```@RunWith(Suite.class)```のように指定する

以下はよく使いそうなテストランナー(他にも種類がある)

- JUnit4
    - public voidメソッド かつ ```@Test```アノテーションがついてるメソッドを対象にすべて実行する
    - AndroidだとAndroidJUnit4を使う
- Suite
    - ```@Suite.SuiteClasses()```で指定したクラスを実行する
- Theories
    - パラメータ化テスト用
    - テストケースとテストデータを別々に定義してテストする
    - ```@Test```ではなく```@Theory```でテスト実行
    - ```@DataPoints```で値の定義    

# Androidのサンプルをみてみる
[GoogleのAndroidJunitRunnerSampleサンプル](https://github.com/googlesamples/android-testing/tree/master/runner/AndroidJunitRunnerSample)のなかにあるコードで実際にJUnit4のアノテーションをみてみます。

[UnitTestSuite.java](https://github.com/googlesamples/android-testing/blob/master/runner/AndroidJunitRunnerSample/app/src/androidTest/java/com/example/android/testing/androidjunitrunnersample/suite/UnitTestSuite.java)

```java
//省略

//テストランナークラスにSuiteを指定
@RunWith(Suite.class) 

//実行するクラスの指定
@Suite.SuiteClasses({CalculatorTest.class, CalculatorAddParameterizedTest.class})
public class UnitTestSuite {}
```

[CalculatorTest.java](https://github.com/googlesamples/android-testing/blob/master/runner/AndroidJunitRunnerSample/app/src/androidTest/java/com/example/android/testing/androidjunitrunnersample/CalculatorTest.java)

```java
//省略

//テストランナークラスにAndroidJUnit4を指定
@RunWith(AndroidJUnit4.class)
@SmallTest
public class CalculatorTest {
    private Calculator mCalculator;
    //初期化処理
    @Before
    public void setUp() {
        mCalculator = new Calculator();
    }
    //実行するテスト
    @Test
    public void addTwoNumbers() {
        double resultAdd = mCalculator.add(1d, 1d);
        //アサーションの実行。　isはMacher
        assertThat(resultAdd, is(equalTo(2d)));
    }
//省略
    //expected で例外のテスト
    @Test(expected = IllegalArgumentException.class)
    public void divDivideByZeroThrows() {
        mCalculator.div(32d, 0d);
    }
//省略
}
```


#参考

- [AndroidTestingSupportLibrary](https://google.github.io/android-testing-support-library/)
- [Testing Support Library](http://developer.android.com/intl/ja/tools/testing-support-library/index.html#features)
- JUnit実践入門 ~体系的に学ぶユニットテストの技法 [Amazonリンク](http://www.amazon.co.jp/dp/477415377X) 
    - JUnitの解説とテスト自体の解説が丁寧に書かれており大変分かりやすかったです。