【问题标题】:Why do large Android Activity Unit-tests fail?为什么大型 Android Activity 单元测试会失败?
【发布时间】:2013-03-19 06:55:11
【问题描述】:

我正在尝试为具有多种测试方法的 Activity 创建单元测试。但是在大约 31 次测试之后,应用程序被终止,因为堆内存不足。

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 速度不够快,无法在测试期间清理内存。

这是我的泄漏测试测试用例:

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);
    }
}

扩展Activity的测试Activity:

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 秒将是一个巨大的延迟。

我希望有人可以帮助我,如果我的问题不清楚,请告诉我。

提前致谢。

【问题讨论】:

    标签: android unit-testing junit


    【解决方案1】:

    为什么每次单元测试后都需要做一次 gc?

    如果是因为您想要一个干净的测试环境,那么请忍受 2 秒的延迟。 tearDown 至少进行 2 次 gc 和一些最终确定。它为您的下一次测试留下了一个干净的环境。如果你通读android源代码,有几个cmet表明在测试结束时调用tearDown的迫切需要。

    如果您的测试不需要干净的环境,请将它们组合起来。话虽如此,在后台运行 200 秒的进程对于测试将为您提供的保护付出的代价很小。

    我们对当前大型项目的自动化测试大约需要 5 分钟才能运行。我从来没有注意到,因为我们已经自动化了我们的系统以在初始签入时运行测试,如果测试失败则退回提交。

    他们几次都失败了,我真的很震惊,因为我更改的代码搞砸了应用程序的其他部分。通过我们的自动化测试,我们至少节省了数周甚至数月的维护和调试应用。

    【讨论】:

    • 您好,感谢您的回复。我希望我们当前测试中的每个测试都有一个全新的活动。这样前一个测试就不会影响下一个测试。但我觉得奇怪的是 2 秒的延迟修复了 OutOfResourcesException creating surface 错误。感觉就像是 Android 中的一个错误,或者没有足够快地释放表面资源的东西。但现在我们只接受 2 秒的延迟,因为它每天都在快速构建设置上运行。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-26
    • 1970-01-01
    • 2022-06-29
    • 2012-07-03
    相关资源
    最近更新 更多