一、Espresso Intents简介
Espresso Intents 是Espresso的扩展,使在测试时应用时验证 Intents 的有效性和发送携带数据的intent成为可能。它与Mockito很像,但是是Android中的意图。
1.1 下载Espresso Intents
确保你安装了Android Support Repository(详情查看 instructions)。
打开你app层的build.gradle文件。这个通常不是顶层的build.gradle文件,而是app层的build.gradle文件。加载下面的依赖:
androidTestCompile 'com.android.support.test.espresso:espresso-intents:2.2.2'Espresso
- 意图只与Espresso2.1+和测试支持包0.3兼容,所以注意更新下面几行:
androidTestCompile 'com.android.support.test:runner:0.5'
androidTestCompile 'com.android.support.test:rules:0.5'
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
1.2 测试规则
Use IntentsTestRule instead of ActivityTestRule when using Espresso-Intents. IntentsTestRule makes it easy to use Espresso-Intents APIs in functional UI tests.
This class is an extension of ActivityTestRule, which initializes Espresso-Intents before each test annotated with @Test and releases Espresso-Intents after each test run.
The activity will be terminated after each test and this rule can be used in the same way as ActivityTestRule.
当使用Espresso意图时使用IntentsTestRule而不是ActivityTestRule 。在进行有效的UI测试时IntentsTestRule使使用Espresso意图更加简便。
在测试完成后,Activity将终止,在ActivityTestRule中也可以以相同的方式使用
1.3 验证 intent的有效性
Espresso-Intents记录了在测试应用时 所有尝试启动的Activity 的 intent.
使用intent的API(类似于Mockito.verify),你可以断言指定的intnet是否被接收
下面是一个简单的验证intent已经发出的的例子:
@Test
public void validateIntentSentToPackage() {
//用户的动作,结果是启动一个外部的“phone”Activity
user.clickOnView(system.getView(R.id.callButton));
// Using a canned RecordedIntentMatcher to validate that an intent resolving
// to the "phone" activity has been sent.
//通过封装的RecordeIntentMatcher来验证作用于“phone” activity的intent已经被发送
intended(toPackage("com.android.phone"));
}
1.4 携带参数的intent
使用intent API(类似于Mockito.when),你可以为”通过startActivityForResult方法打开的Activity”设置一个返回结果(对于无法操控用户操作,也不能控制在测试环境下返回结果的activity尤其重要):
下面是携带参数的intent的例子:
@Test
public void activityResult_IsHandledProperly() {
//当activity启动时创建一个将要返回的结果
Intent resultData = new Intent();
String phoneNumber = "123-345-6789";
resultData.putExtra("phone", phoneNumber);
ActivityResult result = new ActivityResult(Activity.RESULT_OK, resultData);
//当intent发送到com.android.contacts时设置返回结果
intending(toPackage("com.android.contacts")).respondWith(result));
//"contacts" activity被启动的动作
//启动一个activity并返回一个电话号码,显示在屏幕中
onView(withId(R.id.pickButton)).perform(click());
//断言上面所设置的数据被显示了
onView(withId(R.id.phoneNumber).check(matches(withText(phoneNumber)));
}
1.6 Intent matchers
intending(..) 和 intended(..)方法都使用 hamcrest Matcher 作为参数。
Hamcrest is library of matcher objects (also known as constraints or predicates). You have these options:
- Use an existing intent matcher: Easiest option, which should almost always be preferred.
- Implement your own intent matcher: Most flexible option (see the section entitled “Writing custom matchers” in the Hamcrest tutorial)
Hamcrest是matcher对象的library(与constraints和predicates类似)。你有以下选项:
使用一个已经存在匹配器:最简单也是最常用的选择
自定义匹配器:更灵活的选择(更多请查看Hamcrest tutorial部分“自定义匹配器”)
方式一的简单示例,使用已存在的intent匹配器验证intent有效性的例子:
intended(allOf(
hasAction(equalTo(Intent.ACTION_VIEW)),
hasCategories(hasItem(equalTo(Intent.CATEGORY_BROWSABLE))),
hasData(hasHost(equalTo("www.google.com"))),
hasExtras(allOf(
hasEntry(equalTo("key1"), equalTo("value1")),
hasEntry(equalTo("key2"), equalTo("value2")))),
toPackage("com.android.browser")));
二、示例
2.1 动态发送Intetn
动态启动MainActivity
- 主界面
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tv = (TextView) findViewById(R.id.tv_hello);
Intent intent = getIntent();
String action = intent.getAction();
System.out.println("action.................."+action);
if (intent.hasExtra("TAG")) {
System.out.println("1..................");
final String tag = getIntent().getStringExtra("TAG");
System.out.println("2.................."+tag);
tv.setText(tag);
System.out.println("3...................设置成功");
}
}
}
- 测试文件
@RunWith(AndroidJUnit4.class)
@SmallTest
public class MainActivityMultipleLaunchIntentTest {
@Rule
public ActivityTestRule<MainActivity> mActivityRule =
new ActivityTestRule<>(MainActivity.class, //所要启动的activity
true, //是否初始化toch mode
true); //是否启动activity,为true时,会先以action为main启动activity一次,为false时,会以设置的action启动activity一次,如果不设置,action
@Test
public void shouldShowHelloMoon() {
//模拟要发送的activity
Context targetContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
Intent intent = new Intent(targetContext, MainActivity.class);
intent.putExtra("TAG", "dynamic send intent");
//启动目标activity
mActivityRule.launchActivity(intent);
//检验结果
onView(withId(R.id.tv_hello)).check(matches(withText("dynamic send intent")));
}
}
- mActivity第三个参数为true时,所运行的结果:目标activity被启动了两次
- mActivity第三个参数为false时的运行结果:目标activity被启动了一次,默认不启动
2.2 修改启动activity时所默认使用的inent
- 主activity中的内容
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tv = (TextView) findViewById(R.id.tv_hello);
if (getIntent().hasExtra("TAG")) {
System.out.println("1..................");
final String tag = getIntent().getStringExtra("TAG");
System.out.println("2.................."+tag);
tv.setText(tag);
System.out.println("3...................设置成功");
}
}
}
- 测试文件的内容
@RunWith(AndroidJUnit4.class)
@SmallTest
public class CustomIntentTest {
@Rule
public ActivityTestRule<MainActivity> mActivityRule =
new ActivityTestRule<MainActivity>(MainActivity.class) {
@Override
protected Intent getActivityIntent() {
Context targetContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
Intent result = new Intent(targetContext, MainActivity.class);
result.putExtra("TAG", "custom intent");
return result;
}
};
@Test
public void shouldShowHelloEarth() {
Context targetContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
Intent result = new Intent(targetContext, MainActivity.class);
result.putExtra("Name", "Earth");
![这里写图片描述](http://img.blog.csdn.net/20170421100101600?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZmVpMjAxMjExMDY=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
onView(withId(R.id.tv_hello)).check(matches(withText("custom intent")));
}
}
- 运行结果:
2.3 启动activityforResult
见1.4代码
2.4 校验
@Large
@RunWith(AndroidJUnit4.class)
public class SimpleIntentTest {
private static final String MESSAGE = "This is a test";
private static final String PACKAGE_NAME = "com.example.myfirstapp";
/* 实例化一个IntentsTestRule对象. */
@Rule
public IntentsTestRule≶MainActivity> mIntentsRule =
new IntentsTestRule≶>(MainActivity.class);
@Test
public void verifyMessageSentToMessageActivity() {
// 在EditText中输入文字.
onView(withId(R.id.edit_message))
.perform(typeText(MESSAGE), closeSoftKeyboard());
// 通过显性的intent向另一个activity发送消息
onView(withId(R.id.send_message)).perform(click());
//检测目标activity收到了intent中包含的相应包名和消息
intended(allOf(
hasComponent(hasShortClassName(".DisplayMessageActivity")),
toPackage(PACKAGE_NAME),
hasExtra(MainActivity.EXTRA_MESSAGE, MESSAGE)));
}
}