您的位置:首页 > 产品设计 > UI/UE

Test run failed: Instrumentation run failed due to 'Process crashed.'解析

2015-01-31 16:20 483 查看
在使用基于Instrumentation测试框架如robotium时,Test run failed: Instrumentation run failed due to 'Process crashed.'这个报错估计大多数人都遇到过,Android的应用是以Linux进程的概念在运行的,而Instrumentation与被测应用运行在同一个进程中,当被测应用的进程在Instrumentation本身退出前被关闭了,则会抛出Test
run failed: Instrumentation run failed due to 'Process crashed.'这样的错误。

测试过程中引起这种情况的主要有两大类:

一、被测工程或测试工程本身代码运行异常导致

这类比较好办,首先手动运行被测的应用,没问题的话就可以排除了。然后看看运行时的错误日志,检查下测试工程的配置之类,一般就可以很快定位到。

二、被测应用的主Activity在调用onDestory()方法时有调用如android.os.Process.killProcess(android.os.Process.myPid())或System.exit(0)这种退出进程的方法

这种情况应该是大多数导致Test run failed: Instrumentation run failed due to 'Process crashed.'的原因

Android应用中基本都会有个主入口的Activity,即应用的启动页,先看看我们常见的“再按一次退出程序”的实现:

/**
	 * 返回键退出应用
	 */
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
	    if(keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN){   
	        if((System.currentTimeMillis()-exitTime) > 2000){  
	            Toast.makeText(getApplicationContext(), "再按一次退出程序", Toast.LENGTH_SHORT).show();                                
	            exitTime = System.currentTimeMillis();   
	        } else {
	           finish();
	            System.exit(0);
	        }
	        return true;   
	    }
	    return super.onKeyDown(keyCode, event);
	}


有些应用是按一次返回键就退出程序了,但道理都是一样的,即应用的主Activity会去监听KEYCODE_BACK事件,当我们点击BACK键时,程序调用System.exit(0)或android.os.Process.killProcess(android.os.Process.myPid())退出程序。

如果你的应用是类似这种实现,那么测试时一般就不会碰到Instrumentation run failed due to 'Process crashed.问题了。

如果你的应用是只要当前Activity被销毁,即在onDestory()方法中调用System.exit(0)的话,且你的测试用例在tearDown()时调用了solo.finishOpenedActivities()方法,且你的测试用例调起了主入口的Activity,由于finishOpenedActivities()会将所有已打开过的Activity都销毁,那么主入口Activity也会被销毁,而Activity被销毁时会调用onDestory()方法,那么此种情况必然每次都会报这个错。

这种情况下网上有的会说在tearDown()时别调用finishOpenedActivities()方法,这显然是不可行的,因为这会使多个测试用例执行时卡住不能往下执行,因为基于Instrumentation的测试框架,生命周期为setUp()——>以test开头的测试方法——>tearDown()

setUp()时会把被测的Activity调起,并做一些初始化相关,然后执行测试方法,最后tearDown()清理数据等,为了保障每个用例尽可能地可靠、稳定、具有原子性,这种框架的生命周期还是得遵守的。

解决办法的话,只能是让开发修改退出程序的方式,不要在主Activity的onDestory()时直接调用System.exit(0)。

其它:当连续执行几百个测试用例时,有时正常、有时又会偶然性地出现Test run failed: Instrumentation run failed due to 'Process crashed.'问题

由上文可知被测应用的主Activity会监听KEYCODE_BACK事件,当你的用例有调起过或测试过程中会经过主Activity时,那么任何带有KEYCODE_BACK的事件都有可能导致报这个错。

在robotium中会发送KEYCODE_BACK的主要用以下两个方法:

一个是goBack()方法:

/**
	 * Simulates pressing the hardware back key.
	 */

	public void goBack() {
		sleeper.sleep();
		try {
			inst.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
			sleeper.sleep();
		} catch (Throwable ignored) {}
	}
对于偶然性地出现这个报错,测试用例中应该不会有人没事老调用goBack()方法,因此应该不会是由于这个引起的。

另一个就是每个用例都会用到的finishOpenedActivities()方法:

/**
	 * All activites that have been opened are finished.
	 */

	public void finishOpenedActivities(){
		// Stops the activityStack listener
		activitySyncTimer.cancel();
		ArrayList<Activity> activitiesOpened = getAllOpenedActivities();
		// Finish all opened activities
		for (int i = activitiesOpened.size()-1; i >= 0; i--) {
			sleeper.sleep(MINISLEEP);
			finishActivity(activitiesOpened.get(i));
		}
		activitiesOpened = null;
		sleeper.sleep(MINISLEEP);
		// Finish the initial activity, pressing Back for good measure
		finishActivity(getCurrentActivity(true, false));
		setRegisterActivities(false);
		this.activity = null;
		sleeper.sleepMini();
		try {
			inst.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
			sleeper.sleep(MINISLEEP);
			inst.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
		} catch (Throwable ignored) {
			// Guard against lack of INJECT_EVENT permission
		}
		clearActivityStack();
	}


由上可知源码的作者在把所有的已打开的Activity都关闭后,还调用了两次inst.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);

其实正常情况下前半段代码就已经能够把所有的已打开的Activity都关闭了,但出于某些特殊情况的考虑,可能在那个for循环中并没能将已打开的Activity均关闭,所以作者还特意多调用了两次KEYCODE_BACK,而这也就带来了较大的出现Instrumentation run failed due to 'Process crashed.'的风险。

解决的话比如可以在inst.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK)前增加判断当前的Activity是否是你应用的主Activity
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐