Android的Activity之间常常借助于intent进行通信,我们可以通过startActivity和startActivityForResult从一个Activity启动另一个Activity,并期望返回结果,借助于Espresso,我们可以对发送的Intent是否正确以及返回的Result进行测试。
使用Espresso对Intent进行测试,首先要在build.gradle(Module:app)的dependencies中加入如下依赖
androidTestCompile('com.android.support.test.espresso:espresso-intents:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
本文我们会用到两个Activity,首先看MainActivity
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.yjp.espressointentdemo.MainActivity">
<Button
android:id="@+id/not_for_result_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/not_for_result"/>
<Button
android:id="@+id/for_result_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/for_result"/>
<TextView
android:id="@+id/result_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" />
</LinearLayout>
用到的字符串资源
<string name="not_for_result">不获取结果</string>
<string name="for_result">获取结果</string>
有两个按钮和一个TextView,看一下代码
package com.yjp.espressointentdemo;
import android.app.Activity;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private static final int REQUEST_CODE = 0;
private TextView mResultTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mResultTextView = (TextView) findViewById(R.id.result_text_view);
Button notForResultButton = (Button) findViewById(R.id.not_for_result_button);
notForResultButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, OtherActivity.class);
startActivity(intent);
}
});
Button forResultButton = (Button) findViewById(R.id.for_result_button);
forResultButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, OtherActivity.class);
startActivityForResult(intent, REQUEST_CODE);
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE
&& resultCode == Activity.RESULT_OK
&& data != null) {
String result = data.getStringExtra("result");
mResultTextView.setText(result);
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
}
两个按钮,一个点击时调用startActivity,另一个点击时调用startActiviyiForResult,TextView用来显示startActivityForResult的返回结果。另一个Activity叫OtherActivity,是一个界面为空白的Activity,我们什么也没实现,甚至于不需要调用setResult返回结果,这里不再给出。稍后测试代码会看到,我们测试MainActivity的Intent行为时,无需实现相关的其他Activity, 只要保证其存在即可。下面就看我们的测试代码
package com.yjp.espressointentdemo;
import android.app.Activity;
import android.app.Instrumentation;
import android.content.Intent;
import android.support.test.espresso.intent.rule.IntentsTestRule;
import android.support.test.runner.AndroidJUnit4;
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.intent.Intents.intended;
import static android.support.test.espresso.intent.Intents.intending;
import static android.support.test.espresso.intent.matcher.ComponentNameMatchers.hasShortClassName;
import static android.support.test.espresso.intent.matcher.IntentMatchers.hasComponent;
import static android.support.test.espresso.intent.matcher.IntentMatchers.toPackage;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static android.support.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.Matchers.allOf;
@RunWith(AndroidJUnit4.class)
public class MainActivityTest {
@Rule
public IntentsTestRule<MainActivity> mIntentsRule =
new IntentsTestRule<>(MainActivity.class);
private String TEST_PAGE_NAME = "com.yjp.espressointentdemo";
@Test
public void testStartActivity() {
//点击不获取结果按钮
onView(withId(R.id.not_for_result_button)).perform(click());
//测试是否对应的Intent被发送
intended(allOf(
hasComponent(hasShortClassName(".OtherActivity")),
toPackage(TEST_PAGE_NAME)));
}
@Test
public void testStartActivityForResult() {
//构造结果Intent
Intent resultIntent = new Intent();
resultIntent.putExtra("result", "OK");
Instrumentation.ActivityResult activityResult =
new Instrumentation.ActivityResult(Activity.RESULT_OK, resultIntent);
//如果有相应的intent发送,并返回虚构的结果
intending(allOf(
hasComponent(hasShortClassName(".OtherActivity")),
toPackage(TEST_PAGE_NAME)))
.respondWith(activityResult);
//点击获取结果按钮
onView(withId(R.id.for_result_button)).perform(click());
//查看是否显示结果
onView(withId(R.id.result_text_view))
.check(matches(withText("OK")));
}
}
有两个测试方法,一个是测试startActivity,我们使用Intended来测试是否发送了发往对应Activity的Intent,而第二个测试方法,用来测试startActivityForResult,但是我们并没有实际获取OtherActivity返回的结果,而是自己构造了一个ActivityResult,然后通过intending进行设置,intending的意思是,如果有发往对应的Activity的intent在其调用后被发送,那么就把构造的ActivityResult返回,所以,我们调用intending后,点击了按钮,这时会调用startActivityForResult,而由于我们intending的调用,此时会返回我们构造的ActivityResult中的Intent给MainActivity的onActivityResult方法。
通过四篇文章,我已经介绍了大部分我使用到的Espresso的功能,第五篇也是最后一篇,我会简单介绍一下测试AdapterView采用的方法。