ちょっと追えていなかったのですがEspresso関連のライブラリが2.1が2015年4月21日に、2.2が2015年5月28日にリリースされたのですね。
ちょっと順に追ってみます。
内容としては、2.0=>2.1では破壊的な変更が発生したので移行時には注意しましょう、でしょうか。ただ、 ActivityInstrumentationTestCase2 を脱却して、 @Rule ベースでアクティビティの起動/終了が管理されるようになったので、個人的には移行をためらう理由もなく、という感じですね。
そのほか、intentなんかも含め、JUnit4らしく?Ruleベースのテストの周辺環境記述に移り変わってきた感じがします。
from 2.0 to 2.1
com.android.support.test:testing-support-lib:0.1がcom.android.support.test:runner:0.2とcom.android.support.test:rules:0.2に分割された- Gradleプロジェクトを書き換えると思うのですが、書き換えた後はGradleのキャッシュを飛ばしてあげましょう。依存関係に不整合が生じるときがあります。
- espressoに以下の新機能が追加されました
- espresso-intents
ActivityTestRuleを拡張したIntentsTestRuleとして、functional UI Testとしてインテントを使えるルールが提供されるようになったらしい
- espresso-core
ViewActionsなんかの機能追加- CheatSheetも更新されてました
- rules
ActivityTestRuleが追加されたことで、 single activityのテストを実施するときにわざわざActivityInstrumentationTestCase2を継承する必要がなくなりましたUiThreadRuleやUiThreadTest、ServiceTestRuleのRuleが追加されたので、これもRuleベースでテストをかけそう- いい感じですね!!
- UIAutomator
UiDevice#dumpWindowHierarchy()の機能追加
- espresso-intents
コード書き換え
ActivityTestRuleが追加されたことで、いままで致し方なく継承していた ActivityInstrumentationTestCase2 から脱却します。
ActivityInstrumentationTestCase2 ベース
@RunWith(AndroidJUnit4.class)
public class MainActivityEspresso extends ActivityInstrumentationTestCase2<MainActivity> {
private MainActivity activity;
@Before
@Override
public void setUp() throws Exception{
super.setUp();
instrumentation = InstrumentationRegistry.getInstrumentation(); injectInstrumentation(instrumentation);
activity = getActivity();
}
@Test
public void example() {
// describe test cases...
}
@After
@Override
public void tearDown() throws Exception {
super.tearDown();
}
}
ActivityTestRule ベース
@RunWith(AndroidJUnit4.class)
public class MainActivityEspresso {
@Rule
public ActivityTestRule<MainActivity> activityRule = new ActivityTestRule<>(MainActivity.class);
@Before
public void setUp(){
activityRule.getActivity(); // Activityが欲しい場合、こう記述する
}
@Test
public void example() {
// describe test cases...
}
}
大分すっきりしました。Activityの起動と破棄が ActivityTestRule に内包されているためです。タイミングはBefore/Afterのとき。
なお、公式のドキュメントを見ればわかるのですが、BeforeのタイミングでActivityを起動しない方法もとることが可能です。
ActivityTestRule(Class activityClass, boolean initialTouchMode, boolean launchActivity) のように宣言することも可能なので、以下のように@Testの中で意図したタイミングでActivityを起動することも可能。ただ、公式では必要最低限に抑えるように、としてますね。
@RunWith(AndroidJUnit4.class)
public class MainActivityEspresso {
@Rule
public ActivityTestRule<MainActivity> activityRule = new ActivityTestRule<>(MainActivity.class, true, false);
@Test
public void example() {
activityRule.launchActivity(intent); // intentを与える
}
}
from 2.1 to 2.2
espresso-web 2.2- EspressoがWebViewもサポートした!!
- おそらく、APIドキュメントの
android.support.test.espresso.web.~というパッケージでまとめられているやつすべてがこれ android.support.test.espresso.web.webdriverがあるので、多分dom取得なんかはAppiumと同じそう。- 話は少し逸れて、AppiumのDroidDriverとか
- おそらく、APIドキュメントの
- EspressoがWebViewもサポートした!!
espresso-core 2.2- Dagger2、hamcrest v1.3の統合
- Espresso内でのinjection、Dagger2ベースになったということかな。
- Dagger2、hamcrest v1.3の統合
espresso-contrib 2.2- Accessibility Checkの追加
- Accessibilityの機能、例えば音声読み上げとかって機能テストする手段がcontentDesctiptionの有無調べるくらいしかなかったので、これは良い感じ
- Accessibility Checkの追加
runner 0.3- JUnit 4.12 ベースへ移行 (from 4.10ベース)
- hamcrest v1.3の統合
rule 0.3DisableOnAndroidDebugの追加
基本的に全体的な不具合修正や少しづつな機能拡張なのですが、 contrib を導入したりするときにGradleの書き方でハマったのでメモ。
Gradleの書き方注意点
// espresso-coreがsupport-annotationsの22.2.0(2015年7月20日現在)を持っているので、以下のように強制的に新しいannotationsを使うか、com.android.supportではannotationsを除外する設定が必要です。
// Warning:Conflict with dependency 'com.android.support:support-annotations'. Resolved versions for app (22.2.1) and test app (22.2.0) differ.
configurations.all {
resolutionStrategy.force 'com.android.support:support-annotations:22.2.1'
// or
// androidTestCompile.exclude group: 'com.android.support', module: 'support-annotations'
}
dependencies {
androidTestCompile 'com.android.support.test:runner:0.3'
androidTestCompile 'com.android.support.test:rules:0.3'
// espresso-contrib が espresso-coreを含んでいるので、contribを入れるときはcoreは入れなくてOK
// androidTestCompile('com.android.support.test.espresso:espresso-core:2.2')
// contribはいくつかのcom,android.supportライブラリを内包しているので、以下のようにexcludeする必要があります。除かない場合、java.lang.NoClassDefFoundErrorのエラーがでます。
// java.lang.NoClassDefFoundError: your.package.name
androidTestCompile('com.android.support.test.espresso:espresso-contrib:2.2'){
exclude group: 'com.android.support', module: 'support-v4'
exclude group: 'com.android.support', module: 'recyclerview-v7'
}
androidTestCompile('com.android.support.test.espresso:espresso-web:2.2')
締め
AndroidのEspresso周り、適用範囲を広げてきましたね。iOSのXCUITestもそうなのですが、
(実行時間が短い) JUnit/XCTest < Espresso/XCUITest < uiautomator/UIAutomation (実行時間が長い)
という感じで、機能的なテストツールが拡充されてきた感じ。人海戦術からの脱却も加速しそうですね。イコール、EspressoやXCUITestを書く人は、実装箇所の理解もないと厳しそう。一方、Appiumなどはユーザシナリオと実装を切り離したテストを提供できるので、いままでと変わらず必要そう。結局は、何を目的として、どのような範囲で、何を防ぐかというテストのDesignの話にはなるのですが。
1 Comment