接下来的章节为应用程序UI的测试提供了一些提示,特别是帮助你在UI线程里处理动作,触屏和按键事件,和锁屏。
UI线程中测试
Activity运行在程序的UI线程里。一旦UI初始化后,例如在Activity的onCreate()方法后,所有与UI的交互都必须运行在UI线程里。当你正常运行程序时,它有权限可以访问这个线程,并且不会出现什么特别的事情。
当你运行测试程序时,这一点发生了变化。在带有instrumentation的类里,你可以触发方法在UI线程里运行。其它的测试用例类不允许这么做。为了一个完整的测试方法都在UI线程里运行,你可以使用@UIThreadTest来声明线程。注意,这将会在UI线程里运行方法里所有的语句。不与UI交互的方法不允许这么做;例如,你不能触发Instrumentation.waitForIdleSync()。
如果让方法中的一部分代码运行在UI线程的话,创建一个匿名的Runnable对象,把代码放到run()方法中,然后把这个对象传递给appActivity.runOnUiThread(),在这里,appActivity就是你要测试的app对象。
例如,下面的代码实例化了一个要测试的Activity,为Spinner请求焦点,然后发送一个按键给它。注意:waitForIdleSync和sendKeys不允许在UI线程里运行:
private MyActivity mActivity; // MyActivity is the class name of the app under test
private Spinner mSpinner;
...
protected void setUp() throws Exception {
super.setUp();
mInstrumentation = getInstrumentation();
mActivity = getActivity(); // get a references to the app under test
/*
* Get a reference to the main widget of the app under test, a Spinner
*/
mSpinner = (Spinner) mActivity.findViewById(com.android.demo.myactivity.R.id.Spinner01);
...
public void aTest() {
/*
* request focus for the Spinner, so that the test can send key events to it
* This request must be run on the UI thread. To do this, use the runOnUiThread method
* and pass it a Runnable that contains a call to requestFocus on the Spinner.
*/
mActivity.runOnUiThread(new Runnable() {
public void run() {
mSpinner.requestFocus();
}
});
mInstrumentation.waitForIdleSync();
this.sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
关闭触屏模式
为了控制从测试程序中发送给模拟器或设备的按键事件,你必须关闭触屏模式。如果你不这么做,按键事件将被忽略。
关闭触摸模式,你需要在调用getActivity()启动Activity之前调用ActivityInstrumentationTestCase2.setActivityTouchMode(false)。你必须在非UI线程中运行这个调用。基于这个原因,你不能在声明有@UIThread的测试方法调用。可以在setUp()中调用。
模拟器或设备的解锁
你可能已经发现,如果模拟器或设备的键盘保护模式使得HOME画面不可用时,UI测试不能正常工作。这是因为应用程序不能接收sendKeys()的事件。避免这种情况最好的方式是在启动模拟器或设备时关闭键盘保护模式。
你还可以显式地关闭键盘保护。这需要在manifest文件中添加一个权限,然后就能在程序中关闭键盘保护。注意,你必须在发布程序之前移除这个,或者在发布的程序中禁用这个功能。
在<manifest>元素下添加<uses-permission android:name=”androd.permission.DISABLE_KEYGUARD”/>。为了关闭键盘保护,在你测试的Activity的onCreate()方法中添加以下代码:
mKeyGuardManager = (KeyguardManager)getSystemService(KEYGUARD_SERVICE);
mLock = mKeyGuardManager.newKeyguardLock("activity_classname");
mLock.disableKeyguard();
这里,activity_classname是Activity的类名。
UI线程中测试
Activity运行在程序的UI线程里。一旦UI初始化后,例如在Activity的onCreate()方法后,所有与UI的交互都必须运行在UI线程里。当你正常运行程序时,它有权限可以访问这个线程,并且不会出现什么特别的事情。
当你运行测试程序时,这一点发生了变化。在带有instrumentation的类里,你可以触发方法在UI线程里运行。其它的测试用例类不允许这么做。为了一个完整的测试方法都在UI线程里运行,你可以使用@UIThreadTest来声明线程。注意,这将会在UI线程里运行方法里所有的语句。不与UI交互的方法不允许这么做;例如,你不能触发Instrumentation.waitForIdleSync()。
如果让方法中的一部分代码运行在UI线程的话,创建一个匿名的Runnable对象,把代码放到run()方法中,然后把这个对象传递给appActivity.runOnUiThread(),在这里,appActivity就是你要测试的app对象。
例如,下面的代码实例化了一个要测试的Activity,为Spinner请求焦点,然后发送一个按键给它。注意:waitForIdleSync和sendKeys不允许在UI线程里运行:
private MyActivity mActivity; // MyActivity is the class name of the app under test
private Spinner mSpinner;
...
protected void setUp() throws Exception {
super.setUp();
mInstrumentation = getInstrumentation();
mActivity = getActivity(); // get a references to the app under test
/*
* Get a reference to the main widget of the app under test, a Spinner
*/
mSpinner = (Spinner) mActivity.findViewById(com.android.demo.myactivity.R.id.Spinner01);
...
public void aTest() {
/*
* request focus for the Spinner, so that the test can send key events to it
* This request must be run on the UI thread. To do this, use the runOnUiThread method
* and pass it a Runnable that contains a call to requestFocus on the Spinner.
*/
mActivity.runOnUiThread(new Runnable() {
public void run() {
mSpinner.requestFocus();
}
});
mInstrumentation.waitForIdleSync();
this.sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
关闭触屏模式
为了控制从测试程序中发送给模拟器或设备的按键事件,你必须关闭触屏模式。如果你不这么做,按键事件将被忽略。
关闭触摸模式,你需要在调用getActivity()启动Activity之前调用ActivityInstrumentationTestCase2.setActivityTouchMode(false)。你必须在非UI线程中运行这个调用。基于这个原因,你不能在声明有@UIThread的测试方法调用。可以在setUp()中调用。
模拟器或设备的解锁
你可能已经发现,如果模拟器或设备的键盘保护模式使得HOME画面不可用时,UI测试不能正常工作。这是因为应用程序不能接收sendKeys()的事件。避免这种情况最好的方式是在启动模拟器或设备时关闭键盘保护模式。
你还可以显式地关闭键盘保护。这需要在manifest文件中添加一个权限,然后就能在程序中关闭键盘保护。注意,你必须在发布程序之前移除这个,或者在发布的程序中禁用这个功能。
在<manifest>元素下添加<uses-permission android:name=”androd.permission.DISABLE_KEYGUARD”/>。为了关闭键盘保护,在你测试的Activity的onCreate()方法中添加以下代码:
mKeyGuardManager = (KeyguardManager)getSystemService(KEYGUARD_SERVICE);
mLock = mKeyGuardManager.newKeyguardLock("activity_classname");
mLock.disableKeyguard();
这里,activity_classname是Activity的类名。