Hatena::ブログ(Diary)

_development, RSSフィード Twitter

2010-09-04

Unit Testing in Dependency Injection

〜 海藻系男子に捧ぐ 〜

プロジェクトページのGet Started!を見て、「ナニコレ。具象クラスをDIとかありえないんですけどwww」などと吹聴していたわけですが”RoboGuiceやってみた : vvakameの日記” を見てRoboGuiceバカにしてすまんかった、と猛省したのでAndroidでDIでUTなことを書くことにしました。


本エントリでは、RoboGuiceを使ってごく単純なテストを実行する方法を解説します。

RoboGuiceなプロジェクトの作り方などはvvakameさんのエントリを参照してください。



アプリケーションをつくる

まず、テストのためのアプリケーション(つまりフツーのアプリケーションですね)をつくります。

説明で使用するアプリケーションは、画面に"わかめ”と表示する単純なものです。

テストでは、表示が"わかめ"に変わったことをAssertする予定にしておきます。

RoboGuiceを使うので、GuiceActivityを継承してアクティビティを作成します。

アクティビティではonCreate()でテキストビューの表示を"わかめ"に変更します。

本来はこのような文言変更はリソースで指定しますが、なんらかのテストすべきロジックとしてこのようにします。


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<TextView  
    android:id="@+id/text_hello"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="@string/hello"
    />
</LinearLayout>
package com.example.android.roboguice;

import roboguice.activity.GuiceActivity;
import roboguice.inject.InjectView;
import android.os.Bundle;
import android.widget.TextView;

public class MyActivity extends GuiceActivity {

    @InjectView(R.id.text_hello)
    TextView textHello;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        textHello.setText("わかめ");
    }
}


テストの前に。

まず、テスト対象のアプリケーションでクラスパスのエクスポートを行います。

こうしておかないと、テストアプリケーションがテスト対象のプロジェクトのクラス(が依存するクラス)を解決できません。

f:id:esmasui:20100905011324p:image



テストをつくる


さきほどつくったアプリケーションをテストするためのプロジェクトをつくります。

手順は通常のAndroidテストと同じです。

f:id:esmasui:20100905011325p:image

f:id:esmasui:20100905011326p:image



テストクラスをつくります。

RoboGuiceのテストドキュメントには、RoboActivityUnitTestCaseなるクラスが出てきますが無視して通常のActivityUnitTestCaseを使います。


なぜ、無視して良いかというと

  • 配布されているテスト用のjarファイルはMETA-INFしか格納されていないという罠
  • Robo...TestCaseはActivityUnitTestCaseを継承しただけで何も実装されていないという罠

だからですっ。


その他に注意すべき点は、GuiceApplicationを継承するアプリケーションを使用するようにsetApplication()を呼び出すことです。これをしないとテストはClassCastExceptionで終了します。

また、Activityの取得はgetActivity()ではなくstartActivity()を使わないといけません。(なぜかは調べてない)


さらに注意すべき点は、AndroidテストケースはJUnit3なのですが、@MediumTestとつけておけば実行されるため、テストメソッドの名前を test* ではじめなくてはならないというJUnit3ェのシキタリを忘れがち。3とか何年前ですか?

これを守らないと、実行はされますが結果を収集してこずに、テストが実行されませんでしたという謎めいた結果になります。



package com.example.android.roboguice.test;

import roboguice.application.GuiceApplication;
import android.content.Context;
import android.content.Intent;
import android.test.ActivityUnitTestCase;
import android.test.suitebuilder.annotation.MediumTest;
import android.widget.TextView;

import com.example.android.roboguice.MyActivity;
import com.example.android.roboguice.R;

public class MyActivityTest extends ActivityUnitTestCase<MyActivity> {

    final class MyMockApplication extends GuiceApplication {
        MyMockApplication(Context context) {
            attachBaseContext(context);
        }
    }

    Context context;

    public MyActivityTest() {
        super(MyActivity.class);
    }

    @MediumTest
    public void testShouldBeVvakame() {
        Intent intent = new Intent(context, MyActivity.class);
        MyActivity underTest = startActivity(intent, null, null);
        TextView textHello = (TextView) underTest.findViewById(R.id.text_hello);
        assertEquals("わかめ", textHello.getText());
    }

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        context = getInstrumentation().getTargetContext();
        setApplication(new MyMockApplication(context));
    }

}

これをRun As... Android JUnit Testすればテストが実行されて緑のバーが見られます。

緑のバー、みんな好きだよね?

f:id:esmasui:20100905011327p:image



つづく

以上でRoboGuice/JUnit3ェでテストを実行することができました。

しかしこれではDIの恩恵を何も受けていないので次回は、DIの長所をいかしたテストのやりかたを書く予定です。(vvakameさんが)

vvakamevvakame 2010/11/24 10:32 試してみました!出来ました!
僕は1.2でやってみて、同じ手順でOKでした。
でも、リストには1.3RC2が(ry

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/esmasui/20100904/1283617914