sbt-androidでRobolectricのテストを実行
RobolectricはActivityなどのAndroidのライブラリに依存するテストを実機やエミュレータを用いずに、通常のJVM上で実行可能にするフレームワークです。
エミュレータを使わないので高速に動作し、JenkinsなどのCIサーバ上でも通常のテストと同様そのまま実行することができます。
動作原理は以下の記事が詳しいです。
Robolectric - Androidのクラスを端末やエミュレータなしで単体テ…:ITpro
今回はこのRobolectricのテストをsbt-androidから実行する方法を説明します。
方法は大きく2つあり、1つはrobospecsを使ってSpecs2で実行する方法、もう1つはRobolectricが標準で対応しているJUnitを使う方法です。それぞれ以下のメリット、デメリットがあります。
robospecsを使う方法
- メリット
- Specs2を使用してテストを書くことができる
- デメリット
- Robolectricのバージョンが古い(1.1)
JUnitを使う方法
- メリット
- 最新のRobolectricを使用できる
- デメリット
- JUnit 4を使用しなければならない
僕は最新のRobolectricを使用したかったので、RobolectricのテストはJUnitを使うことにしました。Androidのフレームワークに依存しないPOSOなScalaのクラスはSpecs2でテストを書いています。
導入方法
build.sbtのlibraryDependenciesに以下を追加
"org.robolectric" % "robolectric" % "2.1.1" % "test",
"junit" % "junit" % "4.11" % "test",
"com.novocode" % "junit-interface" % "0.8" % "test->default"Robolectricのテストを追加
src/test/scala/com/example/test/MainActivityTest.scala
package com.example.test
import org.junit.runner._
import org.robolectric.annotation.Config
import org.robolectric.{Robolectric, RobolectricTestRunner}
import org.junit.{Test, Before}
import com.example.{TR, MainActivity}
import org.junit.Assert._
@RunWith(classOf[RobolectricTestRunner])
@Config(manifest="src/main/AndroidManifest.xml")
class MainActivityTest {
var activity: MainActivity = null
@Before
def setUp() {
activity = Robolectric.buildActivity(classOf[MainActivity]).create().get()
}
@Test
def searchText() {
val searchText = activity.findView(TR.search_text)
assertNotNull(searchText)
}
}上のテストはあくまでサンプルなので、自分のプロジェクトに合わせて適宜書き換えて下さい。ポイントは以下の部分です。
@Config(manifest="src/main/AndroidManifest.xml")
sbt-androidのプロジェクトではAndroidManifest.xmlはsrc/mainにあると思いますが、JavaのAndroidプロジェクトではプロジェクトのルートディレクトリに通常存在します。Robolectricは実行時にカレントディレクトリ(通常はプロジェクトのルートディレクトリ)にあるAndroidManifest.xmlを読もうとするため、上記のようにしてAndroidManifest.xmlを指定しないとエラーとなってしまいます。またnew Activity()のように直接Activityをnewすると警告が出たため、Robolectric.buildActivityを使用してActivityを取得しています。
実行
$ sbt test
Specs2、JUnitのテストが同じプロジェクトに混在していてもきちんと全てのテストが実行され、結果も集計されて表示されます。ほんとよくできてますよね!