在大量和长期的自动化测试中,如果你要使你的测试程序稳定运行,增强其永远不能被杀掉的功能是重中之重,特别是测试压力测试过程中,在极限条件下,如何确保测试程序不会被系统自带的处理机制给kill是非常重要的。
Android后台服务处理机制
低内存
android:priority="1000"
当然最好的方式还是要避免出现低内存的情况,因为自动化测试需要一个稳定的测试环境保证每次的测试一致,如果在测试过程中出现了低内存,可以检查下是不是系统的某个测试场景有内存泄露情况。
运行时间过长
在运行onStartCommand后service进程被kill后,那将保留在开始状态,但是不保留那些传入的intent。不久后service就会再次尝试重新创建,因为保留在开始状态,在创建 service后将保证调用onstartCommand。如果没有传递任何开始命令给service,那将获取到null的intent。
2、START_NOT_STICKY
在运行onStartCommand后service进程被kill后,并且没有新的intent传递给它。Service将移出开始状态,并且直到新的明显的方法(startService)调用才重新创建。因为如果没有传递任何未决定的intent那么service是不会启动,也就是期间onstartCommand不会接收到任何null的intent。
3、START_REDELIVER_INTENT
在运行onStartCommand后service进程被kill后,系统将会再次启动service,并传入最后一个intent给onstartCommand。直到调用stopSelf(int)才停止传递intent。如果在被kill后还有未处理好的intent,那被kill后服务还是会自动启动。因此onstartCommand不会接收到任何null的intent。
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
flags = START_STICKY;
return super.onStartCommand(intent, flags, startId);
}
服务放到前台;经过长时间的经验得出来,如果要保证服务的稳定性,放到前台是最有效的方法,
@Override
public void onStart(Intent intent, int arg1) {
super.onStart(intent, arg1);
// StartForeground
Notification notification = new Notification(R.drawable.icon, getText(R.string.app_name),
System.currentTimeMillis());
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, getText(R.string.app_name), getText(R.string.txt_running), pendingIntent);
startForeground(1, notification);
}
选择更适合自动化测试的实现方法
class TestHandler extends Handler {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
// Scheme before test
case START_SCHEME:
schemeNumber = 0;
// 这儿执行公共的测试环境预置程序,如设置开关、状态、填充等操作
mHandler.sendEmptyMessage(RUN_SCHEME);
break;
case RUN_SCHEME:
if (schemeNumber == StaticData.chooseArray.length) {
mHandler.sendEmptyMessage(END_SCHEME);
} else {
if (StaticData.chooseArray[schemeNumber])
startScheme(schemeNumber);
else {
schemeNumber++;
mHandler.sendEmptyMessage(RUN_SCHEME);
}
}
break;
case END_SCHEME:
mHandler.sendEmptyMessageDelayed(START_TEST, 2000);
break;
case START_TEST:
// init test number
testNumber = 0;
// start run
mHandler.sendEmptyMessage(RUN_TEST);
break;
case RUN_TEST:
if (null == StaticData.runList) {
return;
}
if (testNumber == StaticData.runList.size()) {
if (StaticData.runState.equals("circle")) {
testNumber = 0;
mHandler.sendEmptyMessageDelayed(RUN_TEST, 3000);
} else {
StaticData.testFinishEvent = getResources().getString(R.string.txt_finish_case);
mHandler.sendEmptyMessageDelayed(END_TEST, 3000);
}
} else {
StaticData.runList.get(testNumber);
StaticData.caseNumber = StaticData.runList.get(testNumber).runCaseNumber;
int caseTime = StaticData.runList.get(testNumber).runNumber;
// start
startRunCase(StaticData.caseNumber, caseTime);
}
break;
case END_TEST:
stopSelf();
android.os.Process.killProcess(android.os.Process.myPid());
break;
}
}
};
然后
在每一次用例的执行的时候新建一个Thread运行具体的测试步骤及可,在执行结束的时候再发消息给handler表示可以执行下一条用例了,具体程序如下:
// read txt
// 1 time=5 minutes
private void testCase_1(final int caseTime) {
Thread currentThread = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < caseTime; i++) {
mFunction.killAllActivities();
mOperate.sleep(2000);
File file = new File(StaticData.TEXT_URL);
Uri uri = Uri.fromFile(file);
Intent intent = new Intent();
intent.setAction("android.intent.action.VIEW");
intent.addCategory("android.intent.category.DEFAULT");
intent.setDataAndType(uri, "text/plain");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setPackage("com.android.reader");
mContext.startActivity(intent);
mOperate.sleep(3000);
mNodeOperate.clickOnText(stringArray[0], 2000);
mNodeOperate.clickOnText(stringArray[1], 2000);
mNodeOperate.clickOnText(stringArray[2], 2000);
mNodeOperate.clickOnText(stringArray[3], 2000);
long startTime = System.currentTimeMillis();
while (!Time.isTimeOver(startTime, 5)) {
clickAlertWindow();
mOperate.clickOnScreen(Global.SCREEN_WIDTH - 100, Global.SCREEN_HEIGHT / 2);
mOperate.sleep(10000);
}
mOperate.sendKeyDownUpSync(KeyEvent.KEYCODE_HOME);
mOperate.sleep(2000);
}
// end case
// print log
mEventHandler.sendEmptyMessage(PRINT_LOG);
}
});
currentThread.start();
}