wuzhixiu00 2015-04-13
Activity 的单元测试,每个Activity都是单独运行的,独立于系统环境。做单元测试的时候同个应用中的Activity互不相连,互相独立,每个Activity会单独启动,执行完测试用例后,Activity自动关闭。下面的图是android.test类图结构。
InstrumentationTestCase类
继承自JUnit TestCase类,并可以使用Instrumentation框架,用于测试Activity。使用Instrumentation,Android可以向程序发送事件来自动进行UI测试,并可以精确控制Activity的启动,监测Activity生命周期的状态。
基类是InstrumentationTestCase。它的所有子类都能发送按键或触摸事件给UI。子类还可以注入一个模拟的Intent。
子类有:
n ActivityTestCase——Activity测试类的基类。
n SingleLaunchActivityTestCase——测试单个Activity的类。它能触发一次setup()和tearDown(),而不是每个方法调用时都触发。如果你的测试方法都是针对同一个Activity的话,那就使用它吧。
n ActivityUnitTestCase——对单个Activity进行单一测试的类。使用它,你可以注入模拟的Context或Application,或者两者。它用于对Activity进行单元测试。不同于其它的Instrumentation类,这个测试类不能注入模拟的Intent。
n ActivityInstrumentationTestCase2——在正常的系统环境中测试单个Activity的类。你不能注入一个模拟的Context,但你可以注入一个模拟的Intent。另外,你还可以在UI线程(应用程序的主线程)运行测试方法,并且可以给应用程序UI发送按键及触摸事件。
n SyncBaseInstrumentation——测试Content Provider同步性的类。它使用Instrumentation在启动测试同步性之前取消已经存在的同步对象。
Avtivity单元测试简单举例如下:
被测类:
publicclass MainActivity extends ActionBarActivity {
@Override
protectedvoid onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
View toLoginView = findViewById(R.id.to_login);
mUsernameView = (EditText) //输入框
mMainActivity.findViewById(R.id.username); //提交按钮
toLoginView.setOnClickListener(new View.OnClickListener(){
publicvoid onClick(View view) {
Intent intent = new Intent(getApplicationContext(),
LoginActivity.class);
startActivity(intent);
}
});
}
}
测试类:
publicclass MainActivityTests extends
ActivityInstrumentationTestCase2<MainActivity> {
private MainActivity mMainActivity;
private Instrumentation mInstrumentation;
private View mToLoginView;
privatestaticinti = 0;
// 此构造函数一定要提供
public MainActivityTests() {
super(MainActivity.class);
}
@Override
protectedvoid setUp() throws Exception {
super.setUp();
// 如果要发送键盘事件一定要关闭触摸模式。不然键盘事件将被忽略。
setActivityInitialTouchMode(false);
// 可以发送键盘事件的对象
mInstrumentation = getInstrumentation();
// 启动avtivity,此函数每执行一次,activity就会启动一次。
mMainActivity = getActivity();
// 输入框
mUsernameView = (EditText) mMainActivity.findViewById(R.id.username);
// 提交按钮
mToLoginView = mMainActivity.findViewById(R.id.to_login);
}
publicvoid testPreConditions() {
assertTrue(mToLoginView != null);
}
publicvoid testToLogin() {
//和UI相关的操作要放在UI线程中执行。
/*
* instrumentation.runOnMainSync();等同于一下两个函数
* mActivity.runOnUiThread();//主线程中运行UI操作
* mInstrument.waitForIdleSync();//等待UI同步
*/
// mMainActivity.runOnUiThread(new Runnable() {
// public void run() {
// mUsernameView.requestFocus();
// }
// });
// // 因为测试用例运行在单独的线程上,这里最好要
// // 同步application,等待其执行完后再运行
// mInstrumentation.waitForIdleSync();
mInstrumentation.runOnMainSync(new Runnable() {
@Override
publicvoid run() {
mUsernameView.requestFocus();//获得焦点
}
});
sendKeys(KeyEvent.KEYCODE_Y, KeyEvent.KEYCODE_U, KeyEvent.KEYCODE_A, KeyEvent.KEYCODE_U);//输入字符
mInstrumentation.runOnMainSync(new Runnable() {
@Override
publicvoid run() {
mToLoginView.requestFocus();
mToLoginView.performClick();//执行提交按钮的click事件
}
});
}
}