なか日記

一度きりの人生、楽しく生きよう。

Robolectricを使ったUnitTest(最後まで見てね)

テスト部第6回MTG(Android)で知ったRobolectricを試してみようと、Eclipse Quick Start | Robolectricを見ながら試してみましたが、私の英語力の低さにより(?)うまくいかなかったので、じっくりと意訳しながら試してみます。

下準備

Downloads | Robolectricから robolectric-X.X.X-all.jar をダウンロードしておきます。
robolectric-X.X.X.jar をダウンロードすると私のように残念な結果になってしまいます。

Androidプロジェクトの作成

新規Androidプロジェクトのダイアログ
  • プロジェクト名:MyProject
  • ビルド・ターゲット:ターゲット名: “Google APIs”, ベンダー: “Google Inc.”, プラットフォーム“2.2”, Apiレベル: “8”
  • アプリケーション名:MyProject
  • パッケージ名:com.example
  • アクティビティーの作成:MyActivity
  • 最小SDKバージョン:8
  • 最後に完了を押す(テストプロジェクトは作成しない)
テスト用ソースディレクトリを追加
  • パッケージエクスプローラの‘MyProject’で右クリックして、新規→フォルダー(ソース・フォルダーを作成しないこと)
  • フォルダー名:test
  • 完了を押す

テスト用のJavaプロジェクト作成

テスト用Javaプロジェクトの作成と設定
  • ファイル→新規→Javaプロジェクト
  • プロジェクト名:MyProjectTest
  • 次へを押す
  • MyProjectTestを展開して、その下にある“src”を選択
  • 「ソース・フォルダー 'src' をビルド・パスから除去」のリンクをクリック
  • 「追加ソースのリンク」をクリック
  • 参照ボタンを押して、”..\MyProject\test”を選択
  • 完了ボタンを押す
Androidプロジェクトの参照を追加
  • プロジェクトタブを選択する
  • “追加”を押す
  • “MyProject”にチェックをつける
  • “OK”を押す
  • “完了”をクリックして、新規Javaプロジェクトのダイアログを閉じる

テスト用プロジェクトにjarファイルを追加

エクスプローラでもコマンドラインでもいいので、

  • MyProjectTest の下に lib ディレクトリを作成する
  • lib ディレクトリに robolectric-X.X.X-jar-with-dependencies.jar robolectric--X.X.X-all.jar をコピーする

ビルドパスの設定

Eclipseに戻る
  • “MyProjectTest”で右クリック
  • “リフレッシュ”を選択(libフォルダが表示される)
  • “MyProjectTest”で右クリック
  • “ビルドパス”を選択→“ビルド・パスの構成”
JUnitライブラリの追加
  • “ライブラリー”タブを選択
  • “ライブラリー”の追加
  • JUnit”を選択
  • “次へ”をクリック
  • “JUnit4”を選択(Robolectric は JUnit3 と互換性がない)
  • “完了”をクリック (MyProjectTestのプロパティーは開いたまま)
Robolectric の jar を追加
  • “Jar 追加”をクリック
  • MyProjectTest → lib を展開
  • robolectric-X.X.X-jar-with-dependencies.jar robolectric--X.X.X-all.jar を選択
  • “OK”をクリック (MyProjectTestのプロパティーは開いたまま)
Android の jar を追加
  • “外部 Jar 追加”をクリック
  • \platforms\android-8\android.jar を選択
  • “開く”をクリック (MyProjectTestのプロパティーは開いたまま)
  • “外部 Jar 追加”をクリック
  • \add-ons\addon_google_apis_google_inc_8\libs\maps.jar を選択
  • “開く”をクリック (MyProjectTestのプロパティーは開いたまま)
  • MyProjectTestプロパティーの“OK”をクリック

テストの実行設定

  • “実行” → “実行構成”
  • ”JUnit”をダブルクリック (“Android JUnit Test”ではないので注意)
  • 名前: MyProjectTestConfiguration
  • “選択されたプロジェクト、パッケージ、またはソース・フォルダー内のすべてのテストを実行”のラジオボタンを選択
  • “検索ボタン”をクリック
  • “MyProjectTest”を選択
  • テスト・ランナー:JUnit 4
  • “複数のランチャーが使用可能です”の“一つ選択”をクリックする
  • “構成固有の設定を使用”をチェック
  • “Eclipse JUnit ランチャー”を選択
  • “OK”をクリック
  • “引数”タブをクリック
  • “作業ディレクトリー:”の下にある“その他:”を選択する
  • “ワークスペース”をクリック
  • “MyProject”を選択(“MyProjectTest”ではない。エディットボックスの中は‘${workspace_loc:MyProject}’になる)
  • “適用”をクリック
  • “閉じる”をクリック

セットアップの検証

  • “MyProjectTest”配下の“test”フォルダーで右クリック
  • “新規”→ ”クラス”
  • パッケージ:“com.example”
  • 名前:“MyActivityTest”
  • “完了”をクリック
  • 下記ソースを追加:
package com.example;

import com.example.MyActivity;
import com.example.R;
import com.xtremelabs.robolectric.RobolectricTestRunner;
import org.junit.Test;
import org.junit.runner.RunWith;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;

@RunWith(RobolectricTestRunner.class)
public class MyActivityTest {

    @Test
    public void shouldHaveHappySmiles() throws Exception {
        String hello = new MyActivity().getResources().getString(R.string.hello);
        assertThat(hello, equalTo("Hello World, MyActivity!"));
    }
}
テストの実行
  • “実行” → “実行構成”
  • “JUnit” → “MyProjectTestConfiguration”を選択
  • “実行”をクリック

実行結果

java.lang.NoClassDefFoundError: javassist/Loader
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(ClassLoader.java:632)
at java.lang.ClassLoader.defineClass(ClassLoader.java:616)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)
at java.net.URLClassLoader.access$000(URLClassLoader.java:58)
at java.net.URLClassLoader$1.run(URLClassLoader.java:197)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
at com.xtremelabs.robolectric.RobolectricTestRunner.isInstrumented(RobolectricTestRunner.java:137)
at com.xtremelabs.robolectric.RobolectricTestRunner.(RobolectricTestRunner.java:86)
at com.xtremelabs.robolectric.RobolectricTestRunner.(RobolectricTestRunner.java:59)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:31)
at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:24)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:57)
at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:29)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:57)
at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:24)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.(JUnit4TestReference.java:32)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestClassReference.(JUnit4TestClassReference.java:25)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createTest(JUnit4TestLoader.java:41)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.loadTests(JUnit4TestLoader.java:31)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:452)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: java.lang.ClassNotFoundException: javassist.Loader
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
... 33 more

なんでやねん・・・

とりあえず呟いてみた













なるほど。全くわからん。。。

@さん、おつきあい頂きありがとうございました。

最後に

ふとググってみました。

で、この時ダウンロードするjarに罠があって、最初 robolectric-0.9.2.jar を使ってたら、javasisstとかのライブラリが入ってなくてうまく動きませんでした。

robolectric-0.9.2-all.jar ここでこっち、all がついている方をダウンロードしておかないと涙目になります。

2010-11-27 - @vvakame の日記

な、ん、だ、とう!

というわけで、早速現時点での最新版「robolectric-0.9.4-all.jar」をダウンロードしてビルドパスのライブラリーを差し替え。
そして実行してみたら・・・

ちゃんと動きました。