SyntaxHighlighter

2012年12月2日日曜日

RobolectricとPowerMockを合わせてAndroidのUnit Test(不完全)

AndroidのUnit Testをするのに、RobolectricとPowerMockを合わせたら良いんじゃないかと思ったら意外と設定が面倒だったのでその記録。
不完全な点は、androidパッケージに関わるクラスについてはPowerMockできないので、例えばActivity内でテスト対象のクラスを直接newしているような場合には差し替えができない。

1. Robolectric用プロジェクトの作成と設定
まずは必要なjarをRobolectricのサイトからダウンロードする。
Sonatypeから落とせって言われるけど、どこから落として良いのかわかりづらい…
全部入りのjarが欲しいのでwith-dependenciesを選択して、右のタブでArtifact Informationを選んでDownloadボタンで落とせる。


次にRobolectric用のプロジェクト(以下、RobolectricTest)を作る。
RobolectricTestは、Android Java Projectではなくて、普通のJava Projectとして作成する。
ビルドパスには以下の4つを設定
その1 Robolectric
さっきダウンロードしたRobolectricのjarをlibディレクトリにでも置いてビルドパスを通しておく。
その2 Android.jar
Android SDKにあるandroid.jarを、RobolectricTargetに合わせたバージョンで外部jarとして登録しておく。ビルドパスの順序で、android.jarがRobolectricのjarより先に読まれるようになっているとエラーが出るので注意すること。
その3 JUnit 4
JUnit 4はAdd Library...で設定しても良いし、jarをダウンロードしてビルドパスに設定してもOK。ただ、少なくともRobolectric-1.1はJUnit 4.11に対応していないので、その点は注意すること。
その4 RobolectricTarget
RobolectricTargetはビルドパス設定のProjectsで設定しておく。

テストコードは、ややこしいことにテスト対象のプロジェクト(以下、RobolectricTarget)の方に作る必要があるので、RobolectricTargetにテストコード用のディレクトリ(以下、unit_test)を作っておく。
RobolectricTest側のソースコードディレクトリは必要無いので、srcがあれば削除して、代わりにさっき作ったRobolectricTargetのunit_testへのリンクをソースコードディレクトリとして設定する。
設定方法は、プロジェクトプロパティのJava Build PathでLink Source...をクリックして、RobolectricTargetのunit_testを指定するだけ。

ここまででRobolectric用のプロジェクト設定は完了。大体こんな感じになっているはず。

2. JUnitの実行設定
RobolectricのテストをJUnitで走らせるのにはちょっと設定が必要なので、Run Configurations...で、JUnit用の新しい設定を作成する。
で、Testタブの設定で、Test RunnerはJUnit 4、LauncherはEclipse JUnit Launcherを選ぶ。(Launcherの設定はRun Configuration設定の下部にリンクでSelect one...かSelect other...みたいな感じで出てるはず)

次に、ArgumentsタブのWorking Directoryの設定をOtherにしてWorkspace...からRobolectricTargetを選ぶ

最後に、EnvironmentタブでANDROID_HOMEを設定する。ValueはAndroid SDKのパス。

3. テストコードを書く
テストコードは以下のような感じで書けばOK。ポイントはテストをテスト対象のActivityがあるパッケージと同じところにすること。こうしないとprotectedなonCreateが呼べなくてハマる。

4. PowerMockの設定
PowerMockの設定のポイントは2つ。RunWithがRobolectricに使われていて使えないので、Ruleで設定することと、PowerMockIgnoreを使ってPowerMockの適用範囲からRobolectric関連のクラスを除外すること。

まず、PowerMock関連のjarを入手する。必要なのはPowerMock本体とPowerMockRule関連のjar。
PowerMock本体のjarはpowermock-mockito-junitのzipファイルをダウンロードしてJUnit以外のjarを、RobolectricTestのlibディレクトリにでも置いてビルドパスを設定すればOK。
PowerMockRule関連のjarは、classloadingにxstreamを選ぶこと。具体的には次のjarをダウンロードする。
powermock-module-junit4-rule
powermock-classloading-base
powermock-classloading-xstream
追加でXStreamのjarも必要なので、Binary distributionをダウンロードして次のjarを使う。
xstream
xpp3_min
xmlpull
これらのjarファイルもPowerMock本体のjarと同様、RobolectricTestのlibディレクトリにでも置いてビルドパスを設定すればOK。
設定は後はだいたいこんな感じになる。

で、テストコードは次のように書く。RuleとPowerMockIgnoreの設定がポイント。(ここでandroid.*をignoreしちゃうので、不完全になってしまうのだが、ignoreしないとRobolectricと喧嘩してうまく動かない…ううむ)

この時点で実行してStub!のエラーが出るようであれば、ビルドパスの読み込み順に問題があるので、android.jarを一番最後の読むようにする。多分xmlpullより後にandroid.jarが読まれていれば大丈夫なはずだけど、ややこしいので最後にした方が良さそう。

と、いうことで不完全ながらRobolectricとPowerMockを同時に使う方法でした。
githubにソースを丸ごと上げておいたので参考までに…。

1 件のコメント:

  1. こんにちは。

    テスティングフレームワークの組み合わせ、面白いですね!

    返信削除