ActivityMonitor类是Google为了InstrumentationTest而加入的一个工具类。
当前Instrumentation可以通过addMonitor去添加,被添加后,当一个新Activity创建,ActivityMonitor就会被检查,如果匹配,它的点击次数(getHits)就会被更新。如果调用结束,一个结果(ActivityResult)就会被回传。
ActivityMonitor也可以通过waitForActivity用来等待Activity的创建成功,将会返回一个匹配Activity的对象。
光讲理论太枯燥了,我们来写一个demo演示下ActivityMonitor的作用吧。
InstrumentationTestCases虽然已经被谷歌标记为@Deprecate,但是还是有很多历史遗留下来的测试工具大量使用的,最典型的大概就是CTS测试了。CTS测试一般手机厂商会关注多一点,简单来说就是兼容性测试。有兴趣同学可以访问官网了解下
这个Demo测试从MainActivity跳转到SecondActivity,确认SecondActivity中的TextView显示的字符串是否符合预期,代码如下。
public class InstrumentationDemoTest extends InstrumentationTestCase {
Instrumentation mInstrumentation;
MainActivity mMainActivity;
private Instrumentation.ActivityMonitor mMonitor;
public InstrumentationDemoTest() {
}
@Override
protected void setUp() throws Exception {
super.setUp();
mInstrumentation = getInstrumentation();
Intent intent = new Intent();
intent.setClassName("com.syuunami.amsdemo", "com.syuunami.amsdemo.MainActivity");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mMainActivity = (MainActivity) mInstrumentation.startActivitySync(intent);//启动MainActivity
mMonitor = new Instrumentation.ActivityMonitor("com.syuunami.amsdemo.SecondActivity",null,false);
mInstrumentation.addMonitor(mMonitor);//添加Monitor
}
@Override
protected void tearDown() throws Exception {
Thread.sleep(2000);
super.tearDown();
}
public void testSecondActivity() {
mMainActivity.gotoSecond();//启动SecondActivity
Activity secondActivity =mMonitor.waitForActivity();
TextView tvshow = secondActivity.findViewById(R.id.tv_show2);
assertEquals("not equals", "Hello!",tvshow.getText().toString());
}
}
此处我们使用的就是ActivityMonitor去监听SecondActivity是否创建成功,并且获取已经创建好的对象,进而对SecondActivity的控件属性做判断。
对了,对Instrumentation不了解的同学,请注意这个测试代码是放在(androidTest)这个文件夹里的哦,另外第一次执行测试的时候请用右键测试文件,点击Run InstrumentationDemoTest 或者直接Ctrl Shift F10.
我在看源码的时候产生了一个疑惑:ActivityMonitor的其中一个构造函数是public ActivityMonitor(IntentFilter which, ActivityResult result, boolean block) {},如果有多个Activity匹配which,那么此时Monitor会监听所有的Activity吗
为此我给上面的demo做了修改:
1.为两个Activity都添加了action为"a.b.c"的IntentFilter.
2.给mInstrumentation添加构造器参数为(intentfilter,null,false)的ActivityMonitor mMonitor2.
测试发现,即使调用了MainAcitivity的gotoSecond方法,mMonitor2的getHits()返回值还是0.仔细一想,应该是gotoSecond方法还是使用了显示Intent启动有关,改为隐式启动后,发现无论测试过程中弹出的选框选择哪个Activity,getHits()都会返回1。
由此得出结论,此时Monitor会监听所有匹配的Activity.
另外突然想到,如果给Intrumentation的startActivitySync()方法传入一个隐式Intent会怎样。结果:
java.lang.RuntimeException:
Intent in process com.syuunami.amsdemo resolved to different process system:ui: Intent { act=a.b.c flg=0x14000000 }
看该方法的源码,有段注释如下:
In addition, if the given Intent resolves to multiple activities, instead of displaying a dialog for the user to select an
activity, an exception will be thrown.
好吧。
可能大家对这篇提到的Instrumentation还不熟悉,下篇我们探讨下它的源码。