AndroidでAssertJを使ってテストする
2015-08-10
QiitaJavaAndroid最近知った AssertJ というテストライブラリを使ってみた AssertJ / Fluent assertions for java
Fluent assertions
とあるように流れるような assertion が出来ると聞いてちょっと気になった
AssertJ の導入
gradle の設定
AssertJ / Fluent assertions for java このページによると Android だと 1.x 系がいいらしい 3.x まで出ているので何となく残念な気持ちになる
dependencies {
androidTestCompile 'org.assertj:assertj-core:1.+'
}
これで導入できる
いくつかのファイルをandroid.packagingOptions
でexlucde
指定する必要があるかも知れない
その場合は以下のようにすればまず問題ない
android {
packagingOptions {
exclude 'META-INF/NOTICE.txt'
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/DEPENDENCIES'
exclude 'META-INF/NOTICE'
exclude 'META-INF/LICENSE'
exclude 'NOTICE.txt'
exclude 'LICENSE.txt'
exclude 'DEPENDENCIES'
exclude 'NOTICE'
exclude 'LICENSE'
exclude 'asm-license.txt'
}
}
テストの書き方
テストファイルでassertThat
を import する
import static org.assertj.core.api.Assertions.assertThat;
これで例えばあるオブジェクトがnull
かどうかをチェックするなら以下のように書ける
assertThat(hogeObject).isNotNull();
このようにassertThat(<テスト対象>).isXXX(<期待値>)
のように流れるように書けるため、書きやすく読みやすいと感じる
また、正規表現で文字列をassertThat
したいとき、junit だとMatcher
クラスを自分で実装したりする必要があった
例えばこんな感じ
class RegexStringMatcher extends BaseMatcher {
private final Pattern mExpectedPattern;
public RegexStringMatcher(String expected) {
mExpectedPattern = Pattern.compile(expected);
}
public static RegexStringMatcher isMatch(String expected) {
return new RegexStringMatcher(expected);
}
@Override
public boolean matches(Object actual) {
String actualStr = (String) actual;
Matcher matcher = mExpectedPattern.matcher(actualStr);
return matcher.find();
}
@Override
public void describeTo(Description description) {
description.appendText("pattern: ").appendText(mExpectedPattern.pattern());
}
}
このRegexMatcher
を import してassertThat(hogeString, RegexStringMatcher.isMatch(pattern));
のようにする必要があった
これが AssertJ だとassertThat(hogeString).matches(pattern);
のようにさくっと書けて最高
よく使うのはisEqualTo
,isNotNull
,isNull
,isInstanceOf
,hasSize
,matches
といったところ。
いろいろあるのでAssertJ の公式を参照
View のテスト
導入
いつものごとく、Square 様が android 用にライブラリを提供している
dependencies {
androidTestCompile 'com.squareup.assertj:assertj-android:1.0.1'
}
これで`'org.assertj:assertj-core'も導入される
テストの書き方
普通のassertThat
と大体同じに書ける
AssertJ Android by Square, Inc.のページにあるようにisGone
やisVisible
が簡単に書けることが特長であるといえる
findViewById
などして取得した View オブジェクトに対して例えばassertThat(<何かのView>).isVisible()
でassertThat(<何かのView>.getVisibility()).isEqualTo(View.VISIBLE)
と同じ事が出来る
Espresso との比較
個人的には View のテストは AssertJ より Espresso の方が楽かなという印象 View のテストをそれぞれでやったテストファイル全体を載せるとこんな感じ
import android.app.Activity;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.MediumTest;
import android.widget.Button;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.action.ViewActions.click;
import static android.support.test.espresso.assertion.ViewAssertions.matches;
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static org.assertj.android.api.Assertions.assertThat;
@RunWith(AndroidJUnit4.class)
@MediumTest
public class ExampleActivityTest {
Activity mActivity;
@Rule
public ActivityTestRule<StartActivity> activityRule = new ActivityTestRule<>(ExampleActivity.class);
@Before
public void setUp() throws Exception {
mActivity = activityRule.getActivity();
assertThat(mActivity).isNotNull();
}
@Test
public void 画面が表示されているかどうか() {
onView(isDisplayed());
}
@Test
public void ボタンのテストwithEspresso() {
onView(withId(R.id.awesome_button)).check(matches(isDisplayed()));
onView(withId(R.id.awesome_button)).perform(click());
}
@Test
public void ボタンのテストwithAssertJ() {
final Button button = (Button) mActivity.findViewById(R.id.awesome_button);
assertThat(button).isNotNull().isVisible();
mActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
button.performClick();
}
});
}
}
AssertJ を使うと一旦findViewById
をしてインスタンスを取得して、それに対して assertion を行うことになる
また、上に示したように例えばperfomeClick
するためにはActivity#runOnUiThread
を介する必要が生じてしまう
それに対して Espresso であればonView(withId(<id>)).perform(click())
だけで書けるため、コード量も減ることとなる
本当に簡単な null チェックや visiblity チェックだけのテストであれば AssertJ でいいと思うが、ちょっと細かいことをするならあまりおすすめ出来ない感じではある
所感
先日の Android オールスターズでの発表をきいて AssertJ の存在を知った RECRUIT TECHNOLOGIES Member's blog Android オールスターズでテストの話をしました
JUnit よりも AssertJ の方が個人的には流れるように書けるため、書きやすく読みやすいように感じる
Java のテストには AssertJ がオススメ - Qiita こちらの記事で紹介されているようにカスタム Assertion の実装も簡単に出来て、個人差はあると思うが全体的に JUnit よりちょっと良い、という感覚
また、公式でも JUnit からのマイグレーションについて記述があり、比較的移行も簡単だと思う convert your JUnit assertions to AssertJ とりあえず Android Studio の置換窓に
- before -
assertThat\((.+), is\((.+)\)\);
- after -
assertThat\($1\).isEqualTo\($2\);
を入れればある程度置換出来た すでに書かれたテストを置換するほどではないが、新しくテストを書き始めるならこれからはこちらを使えばいいと思う。
from: https://qiita.com/petitviolet/items/c95255bf3e1ccd9766c3