androidの単体テスト(ActivityInstrumentationTestCase2)
この中でActivityクラスのテストに用いるのが、
- ActivityTestCase
- ActivityInstrumentationTestCase2
- ActivityUnitTestCase
あたりの様子。今回はActivityInstrumentationTestCase2に注目してみます。
・com.example.android.apis.view.Focus2ActivityTest
ApiDemosのFocus2ActivityTestはActivityInstrumentationTestCaseを継承したテストクラスです。ただ、現状ActivityInstrumentationTestCaseはdeprecatedになっているため、本来はActivityInstrumentationTestCase2にすべきですね。
public class Focus2ActivityTest extends ActivityInstrumentationTestCase<Focus2> {
public Focus2ActivityTest() {
super("com.example.android.apis", Focus2.class);
}
Focus2クラスに対してのテストのため、上記のように宣言します。
Focus2は「leftButton」、「centerButton」、「rightButton」の3つのボタンが並んでいるAcitivityです。
・AndroidManifest.xml
<application>
<uses-library android:name="android.test.runner" />
</application>
<instrumentation android:name="android.test.InstrumentationTestRunner"
android:targetPackage="com.example.android.apis"
android:label="Tests for Api Demos."/>
Manifestファイルにテスト対象のパッケージを登録します。
※InstrumentationTestRunnerについてはリファレンスにしっかり書いてあるので、ここでは特に書かないことにします。
@MediumTest
public void testGoingRightFromLeftButtonJumpsOverCenterToRight() {
sendKeys(KeyEvent.KEYCODE_DPAD_RIGHT);
assertTrue("right button should be focused", mRightButton.isFocused());
}
右キーを押下したときにフォーカスがrightbuttonに移動していることを確認するテストです。
ここで使用しているsendKeysメソッドはInstrumentationTestCaseのメソッドです。
実はメインスレッドでActivityを操作することはできないらしく、このsendKeysメソッドを呼び出したとき、内部でUI操作用のスレッドを立て、そのスレッドでイベントキーを発行し、処理が終わり、アイドル状態になるまでwaitしています。
それが分かるのが次のテストケースです。
@MediumTest
public void testGoingLeftFromRightButtonGoesToCenter() {
// Give right button focus by having it request focus. We post it
// to the UI thread because we are not running on the same thread, and
// any direct api calls that change state must be made from the UI thread.
// This is in contrast to instrumentation calls that send events that are
// processed through the framework and eventually find their way to
// affecting the ui thread.
getActivity().runOnUiThread(new Runnable() {
public void run() {
mRightButton.requestFocus();
}
});
// wait for the request to go through
getInstrumentation().waitForIdleSync();
assertTrue(mRightButton.isFocused());
sendKeys(KeyEvent.KEYCODE_DPAD_LEFT);
assertTrue("center button should be focused", mCenterButton.isFocused());
}
このテストケースでは、イベントキーを送るのではなく、直接rightbuttonにフォーカスをあてますが、その処理をUI用スレッドにて行っています。
// affecting the ui thread.
getActivity().runOnUiThread(new Runnable() {
public void run() {
mRightButton.requestFocus();
}
});
別スレッドにて操作を行っているため、操作が完了しアイドル状態になるまで、下記メソッドをコールして同期させています。
// wait for the request to go through
getInstrumentation().waitForIdleSync();
Activityに対する操作は別スレッドにて行うというのを意識しておかないと、単体テスト時に泥沼にはまりそうですね。
