在 Android 运行 Espresso 测试时出现了 OutOfMemory 问题。

7
我在Kitkat和Lollipop设备上运行我的Espresso测试套件时遇到了内存不足的问题。但是这个套件在Marshmallow设备上可以完美地运行。以下是更多的细节,如果能够帮助我找到这个问题的根本原因,我将不胜感激。以下是更多的细节:
  1. 只有在一次运行整个测试套件(共175个测试)时才会出现OutOfMemory错误,如果每个测试集单独运行,则不会出现该问题。
  2. 我尝试使用System.gc(),在每个场景运行后调用,但仍然观察到OutOfmemory异常。
  3. 这个异常在每次运行时都会发生在不同的测试脚本上,而且不是特定的功能/测试脚本。
  4. 应用程序中使用的位图已经压缩,因此不确定它是否与图像大小有关。
  5. 以下是最近一次运行的日志:

    java.lang.Thread.run(Thread.java:818) 01-26 14:42:39.770 3476-4264/? E/Watchdog: !@Sync 579 [01-26 14:42:39.778] 01-26 14:42:42.470 3476-3476/? E/MotionRecognitionService: support TA ~ 01-26 14:42:45.180 4265-4317/? E/ContactsProvider_EventLog: Flush buffer to file cnt : 3 size : 0Kb duration : 39ms lastUpdatedAfter : 180367ms 01-26 14:42:52.510 3476-3476/? E/MotionRecognitionService: support TA ~ 01-26 14:42:55.320 446-454/? E/System: Uncaught exception thrown by finalizer 01-26 14:42:56.900 446-454/? E/System: java.lang.OutOfMemoryError: OutOfMemoryError thrown while trying to throw OutOfMemoryError; no stack trace available 01-26 14:42:56.910 446-1088/? E/CrashReporting: ParseCrashReporting捕获了一个OutOfMemoryError异常,为com.capitalone.mobilebanking.dev.debug构建报告。 01-26 14:42:56.910 446-18726/? E/CrashReporting: ParseCrashReporting捕获了一个OutOfMemoryError异常,为com.capitalone.mobilebanking.dev.debug构建报告。 01-26 14:42:56.910 446-446/? E/MonitoringInstrumentation: Exception encountered by: Thread[main,5,main]. 将线程状态转储到输出并为挪威的鹦鹉献上祭品。 java.lang.OutOfMemoryError: 在剩余3960字节和3KB的空闲内存中分配40字节时发生OutOfMemoryError at android.view.View.buildDrawingCacheImpl(View.java:16723) at android.view.View.buildDrawingCache(View.java:16625) at android.view.View.draw(View.java:17231) at android.view.ViewGroup.drawChild(ViewGroup.java:3921) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3711) at android.view.View.buildDrawingCacheImpl(View.java:16759) at android.view.View.buildDrawingCache(View.java:16625) at android.view.View.updateDisplayListIfDirty(View.java:16445) at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3905) at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3885) at android.view.View.updateDisplayListIfDirty(View.java:16424) at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3905) at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3885) at android.view.View.updateDisplayListIfDirty(View.java:16424) at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3905) at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3885) at android.view.View.updateDisplayListIfDirty(View.java:16424) at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3905) at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3885) at android.view.View.updateDisplayListIfDirty(View.java:16424) at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3905) at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3885) at android.view.View.updateDisplayListIfDirty(View.java:16424) at android.view.ViewGroup.recreateChildDisplayList(ViewGroup


你是否采取堆转储来查找内存泄漏?特别是Activity泄漏? - Gabe Sechan
@GabeSechan :我正在运行 QE 咖啡测试,所以不确定如何获取堆转储。你可以在这里指导我吗? - Darshan
{btsdaf} - CoDe
1个回答

5
我在同时运行超过300个Espresso测试时遇到了同样的问题。显然,每个测试后内存没有被清除,导致了OOM错误(OutOfMemoryError)。
为了解决这个问题,我开始使用Android Test Orchestrator,它为您的测试环境提供以下好处:
  • 最小化共享状态。每个测试在自己的Instrumentation实例中运行。因此,如果您的测试共享应用程序状态,则大多数共享状态会在每个测试后从设备的CPU或内存中删除。
  • 要从设备的CPU和内存中删除每个测试后的所有共享状态,请使用clearPackageData标志。
  • 崩溃被隔离。即使一个测试崩溃,它也只会关闭它自己的Instrumentation实例,因此套件中的其他测试仍然可以运行。
我在项目build.gradle文件中添加了Android Test Orchestrator来解决这个问题:
android {
  defaultConfig {
   ...
   testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

   // The following argument makes the Android Test Orchestrator run its
   // "pm clear" command after each test invocation. This command ensures
   // that the app's state is completely cleared between tests.
   testInstrumentationRunnerArguments clearPackageData: 'true'
 }

  testOptions {
    execution 'ANDROIDX_TEST_ORCHESTRATOR'
  }
}

dependencies {
  androidTestImplementation 'androidx.test:runner:1.1.0'
  androidTestUtil 'androidx.test:orchestrator:1.1.0'
}

5
需要注意的是,添加testInstrumentationRunnerArguments clearPackageData: 'true'也会在测试之间清除任何代码覆盖率数据。因此,如果您想从Espresso测试中获取覆盖率报告,则编排器除了可以隔离故障并让其余测试套件运行外,毫无用处。 - ashu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接