とりあえず、
android-test-kit : Espresso の動画を見ましょう。
以下では Eclipse での設定方法を紹介します。
Android Studio での設定方法は Espresso のプロジェクトページ(上記のリンク)にあるので読んでください。
1. Developer options の設定
アニメーションを Off にしましょう。
設定(Settings) → 開発者向けオプション(Developer options)→
以下の3つを全て「アニメーションオフ(Animation off)」にする
- ウィンドウアニメスケール (Window animation scale)
- トランジションアニメスケール(Transition animation scale)
- Animator再生時間スケール(Animator duration scale)
コードからやる方法
2. Espresso をテストプロジェクトに追加する
Espresso には、依存ライブラリとかも含めて1つの jar になっている
standalone 版と、依存ライブラリが別になっている
dependencies 版があります。
mockito と一緒に使う場合は、hamcrest がかぶってエラーになるので、dependencies 版を使います。
standalone 版を使う場合:git clone するなり、zip をダウンロードするなりして、
espresso-1.0-SNAPSHOT-bundled.jar を取得して、テストプロジェクトの libs フォルダに追加します。
dependencies 版を使う場合:
dependencies 版 にある jar を全部 libs フォルダに入れます。
mockito (mockito-all-1.9.5.jar) と一緒に使う場合は、hamcrest-core-1.1.jar と hamcrest-integration-1.1.jar は libs に入れないでください。
テストプロジェクトの AndroidManifest.xml に
<instrumentation
android:name="com.google.android.apps.common.testing.testrunner.GoogleInstrumentationTestRunner"
android:targetPackage="$YOUR_TARGET_APP_PACKAGE"/>
を追加します。
AndroidManifest.xml の例
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.espresso.test"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="19" />
<application>
<uses-library android:name="android.test.runner" />
</application>
<instrumentation
android:name="com.google.android.apps.common.testing.testrunner.GoogleInstrumentationTestRunner"
android:targetPackage="com.example.espresso" />
</manifest>
ウィザードから Android Test Project を作ると、android.test.InstrumentationTestRunner の instrumentation タグが作られますが、消しても大丈夫です。
<instrumentation
android:name="android.test.InstrumentationTestRunner"
android:targetPackage="com.example.espresso" />
GoogleInstrumentationTestRunner を介してテストが走るように Eclipse を設定します。
Eclipse の [Run] - [Run Configurations...]を選択
Run all tests in the selected project, or package にチェックして、
Instrumetation runner: に com.google.android.apps.common.testing.testrunner.GoogleInstrumentationTestRunner を選択して Apply をクリックします。
* クラス単体を対象とした場合(Run a single Test をチェック)、Instrumetation runner: に com.google.android.apps.common.testing.testrunner.GoogleInstrumentationTestRunner を選択すると、
The instrumentation runner must be of type android.test.InstrumentationTestRunner とエラーが出て怒られます。
Espresso ではクラス単体でテストを走らせることはできないってことなのかしら?
Espresso はいくつかの解析データを収集しています。
収集されたくない場合は、disableAnalytics という引数に true を指定して GoogleInstrumentationTestRunner に渡すことでオプトアウトすることができるとドキュメントには書いてあるのですが、方法がよくわかりませんでした。。。
3. Espresso を使う
例として、ログイン画面(MainActivity)でIDとパスワードを入力してボタンを押すと、Welcome画面(MainActivity2)に遷移するアプリを用意しました。
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final EditText idView = (EditText) findViewById(R.id.editText1);
final EditText passView = (EditText) findViewById(R.id.editText2);
final TextView statusView = (TextView) findViewById(R.id.textView3);
findViewById(R.id.button1).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
statusView.setText("");
String id = idView.getText().toString();
if (TextUtils.isEmpty(id)) {
statusView.setText("IDが入力されていません");
return;
}
String pass = passView.getText().toString();
if (TextUtils.isEmpty(pass)) {
statusView.setText("Passwordが入力されていません");
return;
}
if (check(id, pass)) {
Intent intent = new Intent(MainActivity.this, MainActivity2.class);
intent.putExtra("id", id);
startActivity(intent);
} else {
statusView.setText("IDとPasswordの組み合わせが違います");
}
}
});
}
boolean check(String id, String pass) {
// dummy
return true;
};
}
ログイン画面(MainActivity)では、IDやパスワードが空の場合はステータス用のTextViewにメッセージが表示されます。
つまり
・ID入力用のEditTExtが空のときにステータス用のTextViewにメッセージが表示されるか
・Password入力用のEditTextが空のときにステータス用のTextViewにメッセージが表示されるか
をテストできます。
ログインできる場合は、Intentのextraにidを入れて、Welcome画面(MainActivity2)を開いています。
public class MainActivity2 extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
String id = getIntent().getStringExtra("id");
TextView tv = (TextView) findViewById(R.id.textView1);
tv.setText("ようこそ" + id + "さん");
}
}
Welcome画面(MainActivity2)では、渡されたidをTextView に表示しています。
ここでは、
・ログイン画面で入力されたIDがWelcome画面に表示されるか
をテストできます。
では、テストクラスを作っていきます。
Espresso, ViewActions, ViewMatchers, ViewAssertions, Matchers などの主要 static メソッドを import static で定義しておきましょう。
Espresso のドキュメントに載っているサンプルコードはみな import static した後のコードです。そのことを知ってないとコードをみてもよくわからないでしょう。
ドキュメントのコードをコピペするときにも不便なので、以下の import static をテストクラスにコピペしておきましょう。
import static com.google.android.apps.common.testing.ui.espresso.Espresso.onData;
import static com.google.android.apps.common.testing.ui.espresso.Espresso.onView;
import static com.google.android.apps.common.testing.ui.espresso.Espresso.pressBack;
import static com.google.android.apps.common.testing.ui.espresso.action.ViewActions.click;
import static com.google.android.apps.common.testing.ui.espresso.action.ViewActions.closeSoftKeyboard;
import static com.google.android.apps.common.testing.ui.espresso.action.ViewActions.typeText;
import static com.google.android.apps.common.testing.ui.espresso.assertion.ViewAssertions.matches;
import static com.google.android.apps.common.testing.ui.espresso.matcher.ViewMatchers.withId;
import static com.google.android.apps.common.testing.ui.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
Espresso は Activity を起動してくれないので、setUp() で getActivity() を呼んで Activity を起動する必要があります。
package com.example.espresso;
import static com.google.android.apps.common.testing.ui.espresso.Espresso.onView;
import static com.google.android.apps.common.testing.ui.espresso.action.ViewActions.click;
import static com.google.android.apps.common.testing.ui.espresso.action.ViewActions.typeText;
import static com.google.android.apps.common.testing.ui.espresso.assertion.ViewAssertions.matches;
import static com.google.android.apps.common.testing.ui.espresso.matcher.ViewMatchers.withId;
import static com.google.android.apps.common.testing.ui.espresso.matcher.ViewMatchers.withText;
import android.test.ActivityInstrumentationTestCase2;
public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity> {
public MainActivityTest() {
super(MainActivity.class);
}
@Override
public void setUp() throws Exception {
super.setUp();
// Espresso will not launch our activity for us, we must launch it via
// getActivity().
getActivity();
}
public void testEmptyId() {
// IDを空のままログインボタンをクリック
onView(withId(R.id.button1)).perform(click());
// ステータス用のTextViewにメッセージが表示されるかチェック
onView(withId(R.id.textView3)).check(matches(withText("IDが入力されていません")));
}
public void testEmptyPassword() {
// IDを入力
onView(withId(R.id.editText1)).perform(typeText("yanzm"));
// Passwordを空のままログインボタンをクリック
onView(withId(R.id.button1)).perform(click());
// ステータス用のTextViewにメッセージが表示されるかチェック
onView(withId(R.id.textView3)).check(matches(withText("Passwordが入力されていません")));
}
public void testLogin() {
// IDを入力
onView(withId(R.id.editText1)).perform(typeText("yanzm"));
// Passwordを入力
onView(withId(R.id.editText2)).perform(typeText("1234567890"));
// ログインボタンをクリック
onView(withId(R.id.button1)).perform(click());
// Welcome画面に表示されるかチェック
onView(withId(R.id.textView1)).check(matches(withText("ようこそyanzmさん")));
}
}
こんな感じです。
他にも、ListView や Spinner などの特定の行の View を指定するために使う onData() などがあります。
参考