over 4 years ago

Android では Junit でユニットテストを行うことができます。Junit でテストを行うにはTestCaseクラスのサブクラスを作成し個々のテストケースを記述することになります。

もし、最近流行の Jenkins などの CI(継続的インテグレーション)システムと連携させ、テスト結果を扱いたい場合、テスト結果を保存できるテストランナーを独自に実装するか、OSS のテストランナーを利用する必要があります。

テストケースを書く

テストプロジェクトを作成する

テストプロジェクトは Eclipse で作成できます。Android Test Project を作成するセットアップウィザードでテスト対象のアプリケーションを指定すれば自動的にテストプロジェクトが作成されます。作成されたテストプロジェクトのフォルダやファイル構成は基本的にアプリケーションプロジェクトと同じですが、アイコン画像や、ランチャー起動のAndroidManifest.xml の設定は必須ではないので不要なら削除しても問題ありません。リソースデータはテストプロジェクト独自のリソースとして利用できるので、テストデータとして利用できます。

テストケースの基本的な形

テストケースは TestCase から派生したサブクラスでなければなりません。

package com.example.hello.test;

import junit.framework.TestCase;

public class MyTestCase extends TestCase {

    public void testMethod(){
        int result = 1 + 1;
        assertTrue(3 > result);
    }

}

これはとても簡単で意味の無いテストケースです。意味が無いというのは、テスト対象のテストをするためのコードが無いという意味です。それはともかく、この例はテストケースのプログラムとしてAndroid上で動作します。TestCaseのクラス内にtest接頭辞で始まるメソッドを書くとテストコードと見なされてテストが実行されます。assert接頭辞で始まるメソッドは、TestCaseの親クラスのAssert由来のものです。Assertメソッドには幾つか種類がありますが、これらはどれもロジックの正当性を判定するために利用できます。また、failというメソッドもあり、これは実行されると強制的にテストを失敗させます。

テストメソッドの実行順番

package com.example.hello.test;

import junit.framework.TestCase;

public class MyTestCase extends TestCase {

    public void testMethod1(){
        int result = 1 + 1;
        assertTrue(3 > result);
    }

    public void testMethod2(){
        int result = 1 + 2;
        assertTrue(3 == result);
    }

    public void testMethod3(){
        int result = 1 + 3;
        assertTrue(3 < result);
    }
}

テストメソッドが複数あるとき、これらは順番に実行されるとは限りません。環境によっては順序が一定にならない場合もあります。もし、テストメソッドの実行順序を固定したいなら、TestSuiteを利用することができます。

package com.example.hello.test;

import junit.framework.Test;
import junit.framework.TestSuite;

public class MyTestSuite extends TestSuite {
    public static Test suite() {
        TestSuite suite = new TestSuite();
        suite.addTest(new MyTestCase("testMethod1"));
        suite.addTest(new MyTestCase("testMethod3"));
        suite.addTest(new MyTestCase("testMethod2"));
        return suite;
    }
}

TestSuiteのサブクラスを作成し、static 修飾子のついた Testインスタンスを返却するsuiteメソッド定義します。addTestの引数はTestCaseのサブクラスになります。ここで注意しなければならないのは、そのサブクラスにテストメソッドの名前を受け取れるコンストラクタが必要になることでです。つまり、上述のMyTestCaseは下の様に修正しなければなりません。

package com.example.hello.test;

import junit.framework.TestCase;

public class MyTestCase extends TestCase {

    public MyTestCase(String string) {
        setName(string);
    }

    public void testMethod1(){
        int result = 1 + 1;
        assertTrue(3 > result);
    }

    public void testMethod2(){
        int result = 1 + 2;
        assertTrue(3 == result);
    }

    public void testMethod3(){
        int result = 1 + 3;
        assertTrue(3 < result);
    }
}

要点は、新しくつくったコンストラクタの中で、TestCase由来のsetName()を呼ぶ必要があることです。なお、TestSuiteからテストを実行する場合、EclipseならPackage ExplorerからTestSuiteのサブクラス上でコンテキストメニューを開きAndroid Junit Testを実行します。

setUp()とtearDown()

setUp()はテストメソッドが実行される前に必ず実行され、tearDown()はテストメソッドの実行終了後に必ず実行されます。これらはどちらもテストメソッド毎に実行されるのであって、全てのテストメソッドが実行される前に一度だけとか実行された後に一度というものではありません。別の言い方をするとテストメソッド毎に毎回実行されます。

TestCaseサブクラスの使い分け

Android APIではTestCaseから派生したサブクラスが幾つかあり、Activity用、Service用、ContentProvider用、Application用等、Androidコンポーネント別にTestCaseが用意されています。例えばTestCaseの直接のサブクラスだとContextが扱えないので、ActivityTestCaseを利用します。

テストプロジェクトのコンテキストを取得する

ActivityTestCaseのサブクラスでは、getActivity()でアプリケーション側のContextが取得できます。しかし、テストプロジェクトのコンテキストではないので、テストプロジェクトのリソースにはアクセスできません。テストプロジェクトのContextは、InstrumentationTestCaseのgetInstrumentation().getContext()で取得できます。

テストを実行する

Eclipseで実行する

Eclipseでテストを実行する場合、Package ExplorerでTestCaseやテストメソッドを対象にテストを実行できます。例えば、MyTestCaseというTestCaseがあったとき、その上でコンテキストメニューを開きAndroid Junit Testを実行すればMyTestCaseだけが実行されますし、その中のtestMethod1()上ならばこのテストしか実行されません。

Antで実行する

AntはJava標準のビルドツールでAndroidでもよく利用されます。Antでテストプロジェクトをビルドするにはbuild.xmlが必要になります。これはandroidコマンドで作成できます。

以下はセットアップからテストの実行の手順例です。

$ cd application-project
$ android update project -p ./
$ ant debug install
$ cd test-project
$ android update project -p ./
$ ant debug install test

android update project は build.xml を生成するためのコマンドです。ant debug install は ant ターゲット debugとinstallを実行するという意味で、debugはプログラムをdebug署名でビルドする、installはパッケージをインストールするという意味があります。 testターゲットはテストを実行するという意味があります。

adbで実行する

上述のantのセットアップが済んでいる前提で下のコマンドを実行します。

テストプロジェクト全体

$ ant debug install
$ adb shell am instrument -w com.example.hello.test/android.test.InstrumentationTestRunner

テストケース/テストスイートを指定する

$ ant debug install
$ adb shell am instrument -w -e class com.example.hello.test.MyTestSuite com.example.hello.test/android.test.InstrumentationTestRunner

-w はテスト実行結果の詳細を出力します。-e class はテスト対象のクラス/テストスイートを指定します。最後の文字列は、テストパッケージ名/テストランナーを意味します。

XMLレポート取得する

Android標準のテストランナーはXMLレポートをファイル出力しません。よって、ライブラリを追加するか、標準のテストランナーのカスタマイズが必要です。色々なライブラリがインターネット上で提供されていますが、android junit reportもその一つです。Apache License 2.0ですので利用しやすいと思います。

セットアップ方法

  1. テストプロジェクトのlibsへandroid-junit-report-.jarを追加する
  2. AndroidManifest.xml のタグ属性android:nameにcom.zutubi.android.junitreport.JUnitReportTestRunnerを記述
  3. ant.properties(なければ新規作成)へtest.runner=com.zutubi.android.junitreport.JUnitReportTestRunnerを追記

Eclipseの場合はさらに設定が必要です。Run Configurations の Instrumentation runner でcom.zutubi.android.junitreport.JUnitReportTestRunnerを指定します。

テストを実行するとレポートファイルが/data/data/アプリケーションパッケージ名/files/junit-report.xmlへ生成されます。後は adb pullなどでホストPCへ持ってくることができます。 

← AndroidAnnotations - コードを減らしメンテナンス性を向上させる Antで自動的に環境切り替えをしてビルドする →