2013-03-19 87 views
6

我試圖用很多方法來測試一個活動的單元測試。但經過大約31次測試後,應用程序因爲堆內存不足而死亡。爲什麼大型Android活動單元測試失敗?

1152 E SurfaceFlinger createSurface() failed, generateId = -12 
1152 W WindowManager OutOfResourcesException creating surface 
1152 I WindowManager Out of memory for surface! Looking for leaks... 
1152 W WindowManager No leaked surfaces; killing applicatons! 
1152 W ActivityManager Killing processes Free memory at adjustment 1 

我已經做了單元測試與40相同的簡單的測試用例只是爲了找到這個問題。但感覺就像GC在測試過程中清理內存的速度不夠快。

這是我的leakTest測試用例:

package my.app; 

import android.os.Debug; 
import android.test.ActivityInstrumentationTestCase2; 
import android.util.Log; 

public class leakTest extends 
     ActivityInstrumentationTestCase2<TestActivityAndroid> { 

    String TAG = "leakTest"; 

    TestActivityAndroid mActivity = null; 

    public leakTest() { 
     super(TestActivityAndroid.class); 
    } 

    protected void setUp() throws Exception { 
     super.setUp(); 
     setActivityInitialTouchMode(false); 

     mActivity = getActivity(); 
    } 

    protected void tearDown() throws Exception { 
     super.tearDown(); 
    } 

    private void printHeapSize() { 
     Log.e(TAG, 
       "NativeHeapAllocatedSize = " 
         + Debug.getNativeHeapAllocatedSize()); 
     Log.e(TAG, "NativeHeapFreeSize = " + Debug.getNativeHeapFreeSize()); 
     Log.e(TAG, "NativeHeapSIZE = " + Debug.getNativeHeapSize()); 
    } 

    public void test_1() { 
     assertNotNull(mActivity); 
    } 

    public void test_2() { 
     assertNotNull(mActivity); 
    } 

    public void test_3() { 
     assertNotNull(mActivity); 
    } 

    public void test_4() { 
     assertNotNull(mActivity); 
    } 

    public void test_5() { 
     assertNotNull(mActivity); 
    } 

    public void test_6() { 
     assertNotNull(mActivity); 
    } 

    public void test_7() { 
     assertNotNull(mActivity); 
    } 

    public void test_8() { 
     assertNotNull(mActivity); 
    } 

    public void test_9() { 
     assertNotNull(mActivity); 
    } 

    public void test_10() { 
     assertNotNull(mActivity); 
    } 

    public void test_11() { 
     assertNotNull(mActivity); 
    } 

    public void test_12() { 
     assertNotNull(mActivity); 
    } 

    public void test_13() { 
     assertNotNull(mActivity); 
    } 

    public void test_14() { 
     assertNotNull(mActivity); 
    } 

    public void test_15() { 
     assertNotNull(mActivity); 
    } 

    public void test_16() { 
     assertNotNull(mActivity); 
    } 

    public void test_17() { 
     assertNotNull(mActivity); 
    } 

    public void test_18() { 
     assertNotNull(mActivity); 
    } 

    public void test_19() { 
     assertNotNull(mActivity); 
    } 

    public void test_20() { 
     assertNotNull(mActivity); 
    } 

    public void test_21() { 
     assertNotNull(mActivity); 
    } 

    public void test_22() { 
     assertNotNull(mActivity); 
    } 

    public void test_23() { 
     assertNotNull(mActivity); 
    } 

    public void test_24() { 
     assertNotNull(mActivity); 
    } 

    public void test_25() { 
     assertNotNull(mActivity); 
    } 

    public void test_26() { 
     assertNotNull(mActivity); 
    } 

    public void test_27() { 
     assertNotNull(mActivity); 
    } 

    public void test_28() { 
     assertNotNull(mActivity); 
    } 

    public void test_29() { 
     assertNotNull(mActivity); 
    } 

    public void test_30() { 
     assertNotNull(mActivity); 
    } 

    public void test_31() { 
     assertNotNull(mActivity); 
    } 

    public void test_32() { 
     assertNotNull(mActivity); 
    } 

    public void test_33() { 
     assertNotNull(mActivity); 
    } 

    public void test_34() { 
     assertNotNull(mActivity); 
    } 

    public void test_35() { 
     assertNotNull(mActivity); 
    } 

    public void test_36() { 
     assertNotNull(mActivity); 
    } 

    public void test_37() { 
     assertNotNull(mActivity); 
    } 

    public void test_38() { 
     assertNotNull(mActivity); 
    } 

    public void test_39() { 
     assertNotNull(mActivity); 
    } 

    public void test_40() { 
     assertNotNull(mActivity); 
    } 
} 

測試活性,其延伸的活動:

package my.app; 

import android.app.Activity; 

import android.os.Bundle; 

public class TestActivityAndroid extends Activity { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
    } 
} 

這裏是天然的自由空間下降到低於30KB和比存儲器使用應用程序被殺害。

 Applications Memory Usage (kB): Uptime: 3804373 Realtime: 3804373 

** MEMINFO in pid 7315 [my.app] ** 
        native dalvik other total 
      size:  4048  3271  N/A  7319 
     allocated:  3942  2306  N/A  6248 
      free:  105  965  N/A  1070 
      (Pss):  844  1590  1806  4240 
    (shared dirty):  1404  4120  2288  7812 
    (priv dirty):  736  672  992  2400 Objects 
      Views:  0  ViewRoots:  0 
    AppContexts:  0  Activities:  0 
      Assets:  2 AssetManagers:  2  
    Local Binders:  11 Proxy Binders:  10 
Death Recipients:  0  
OpenSSL Sockets:   0  
SQL 
      heap:  0  memoryUsed:  0 
pageCacheOverflo:  0 largestMemAlloc:  0 
    Asset Allocations 
    zip:/data/app/my.app-1.apk:/resources.arsc: 1K 

有人有更好的解決方案,在tearDown()內的2秒睡眠?我不喜歡tearDown()內的睡眠。而且由於我們在測試套件中有大約100次測試,所以2秒將會是一個巨大的延遲。

我希望有人可以幫助我,如果我的問題不清楚請讓我知道。

在此先感謝。

回答

2

爲什麼每次單元測試後都需要做一個gc?

如果是因爲你想爲你的測試提供一個乾淨的環境,那麼延遲時間爲2秒。 tearDown做至少2 gc和一些定稿。它爲下一次測試留下了一個乾淨的環境。如果您仔細閱讀了android源代碼,有幾條評論表明在測試結束時callilng tearDown的關鍵需求。

如果您的測試不需要一個乾淨的環境,然後將它們合併。這就是說,在幕後運行200秒的過程對於測試給你的保護來說是一個小的代價。

我們對當前大型項目的自動化測試需要大約5分鐘的時間才能運行。我從來沒有注意到,因爲我們已經使我們的系統自動化,以便在初始登記時運行測試,並在失敗時提交提交。

有幾次他們失敗了,我真的很驚訝,我改變的代碼搞砸了應用程序的其他部分。我們已經節省了至少數週,並且可能需要數月的時間來維護和調試我們的應用程序並進行自動化測試

+0

嗨,謝謝你的回覆。我想在我們目前的測試中爲每一項測試提供一個全新的活動。所以以前的測試不能影響下一個測試。但是我發現奇怪的是2秒的延遲修復了'OutOfResourcesException創建表面'錯誤。這感覺就像是Android中的一個錯誤,或者它不能足夠快地釋放表面資源。但現在我們只會接受2秒延遲,因爲它每天都在快速建立設置中運行。 – kuipers 2013-03-22 12:54:13