連載
» 2012年01月20日 00時00分 公開

Androidアプリを“超”魅力的にする3種類のUIテストAndroidアプリ開発テスト入門(3)(2/3 ページ)

[渡辺悟史,日本Androidの会テスト部]

【1】UI操作による状態変化を確認するテスト

 Android Testing Frameworkを使ったUI操作のテストについて解説します。以下のサンプルを基に説明していきます。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <EditText
        android:id="@+id/editer"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
    />
    <Button
        android:id="@+id/send"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/send"
        android:onClick="onTextUpdate"
    />
    <TextView  
        android:id="@+id/result"
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
    />
</LinearLayout>
main.xml
public class HelloAndroidActivity extends Activity {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
    public void onTextUpdate(View v) {
        EditText edit = (EditText) v.getRootView().findViewById(R.id.editer);
        TextView text = (TextView) v.getRootView().findViewById(R.id.result);
        text.setText(edit.getText());
    }
}
HelloActivity.java

 上記は、テキストフィールドとボタンを用意して、ボタンをクリックしたらテキストフィールドに入力された文字列を「TextView」で表示させるという、単純なアプリケーションです。これを「ActivityInstrumentationTestCase2」クラスを使ってテストしていきます。

初期条件を確認

 まずは、初期条件を確認します。テキストフィールドに何も入力されていないことと、TextViewに何も表示されていないことを確認してみます。

    public void testEditText_initialize() throws Exception {
        EditText edit = (EditText)activity.findViewById(com.example.atec.ui.R.id.editer);
        TextView result = (TextView)activity.findViewById(ccom.example.atec.ui.R.id.result);
        assertEquals(“初期値は空文字”, "", edit.getText().toString());
        assertEquals(“初期値は空文字”, "", result.getText());
    }

イベントの確認

 次に、テキストフィールドに文字列を入力しButtonをクリックしたら、テキストフィールドの値を更新することを確認します。

 特に、このサンプルではレイアウトでonClick()メソッドを指定しています。もしメソッド名を間違えても、コンパイル時には判断できず不安が残ります。正しいメソッド名を記述しているかどうかを確認するテストは自動化しておく価値があります。

    public void testEditText_checkInput() throws Exception {
        final EditText edit = (EditText)activity.findViewById(com.example.atec.ui.R.id.editer);
        final Button button = (Button)activity.findViewById(com.example.atec.ui.R.id.send);
        TextView result = (TextView)activity.findViewById(com.example.atec.ui.R.id.result);
        activity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                edit.requestFocus(); // EditTextにフォーカスを当てる
            }
        });
        instrumentation.waitForIdleSync();
        // sendKeysで文字列を入力する
        sendKeys(KeyEvent.KEYCODE_F);
        sendKeys(KeyEvent.KEYCODE_O);
        sendKeys(KeyEvent.KEYCODE_X);
        activity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                button.performClick();
            }
        });
        instrumentation.waitForIdleSync();
        assertEquals("入力された値は正しい","fox", result.getText().toString());
    }

 ここでは、「EditText」に入力された文字列を、正しいかどうかチェックしています。ここでは、文字列入力にInstrumentationTestCase#sendKey()を使いましたが、EditTextのsetText()を使ってもいいと思います。

「UIスレッド」とは

  ここで気を付けなければいけないのが、Androidは描画やUI操作を、「UIスレッド」という特別なスレッドで実行しているという点です。Androidのテストは、UIスレッドとは別のスレッドで実行されるため、UIに関する処理は、UIスレッドに処理をお願いしなくてはいけません。

  runOnUiThread()は、引数で渡したRunnable実装クラスの処理を、UIスレッドで行ってもらうためのメソッドです。runOnUiThreadを呼んだ後、Instrumentation#waitForIdleSync()によってUIスレッドの処理が完了するまで待ってから、後続の処理を行うようにします。

正常系のテスト以外のテストケースも考えよう

 今回は、正常系のテストのみ行いました。実際の開発は、境界値を考えて文字を入力しない場合や、入力可能な文字列以上の文字列を入力してしまう場合、特殊な文字を入力する場合をテストしておいた方がいいと思います。

 同値分割境界値分析の考え方を基に、テストケースを考えてみてください。

ユーザー操作をエミュレートする「TouchUtils」を使うと

 先ほどのテストを、「TouchUtils」というクラスを使った方法で書き換えてみます。これは、メソッドを直接実行するのではなく、ユーザー操作をエミュレートするためのクラスです。

    public void testEditText_checkButtonClick() throws Exception {
        EditText edit = (EditText)activity.findViewById(com.example.atec.ui.R.id.editer);
        Button button = (Button)activity.findViewById(com.example.atec.ui.R.id.send);
        TextView result = (TextView)activity.findViewById(com.example.atec.ui.R.id.result);
        TouchUtils.clickView(this, edit);
        sendKeys(KeyEvent.KEYCODE_C);
        sendKeys(KeyEvent.KEYCODE_O);
        sendKeys(KeyEvent.KEYCODE_W);
        TouchUtils.clickView(this, button);
        assertEquals("ボタンがクリックされた時の値のチェック", "cow", result.getText().toString());
    }

 こちらの書き方の方が、UIスレッドを意識しないで書けるので、すっきりとします。

 TouchUtilsはタップやスクロールのような操作のエミュレートがメソッドとして提供されています。ドキュメントを参考にしながら、ぜひいろいろ試してみてください。次ページでは、残りの2種のテストについて解説します

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。