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

        在使用基於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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章