在 Android 中进行 运行 espresso 测试时出现内存不足问题

OutOfMemory issue while running espresso tests in Android

我在 Kitkat 和 Lollipop 设备上 运行ing 我的浓缩咖啡测试套件时一直面临这个问题 (OutOfMemory)。该套件 运行 在 Marshmallow 设备上完全没问题。下面是更多详细信息,如果我能在确定此问题的根本原因方面获得任何帮助,我将不胜感激。以下是更多详细信息:

  1. OutofMemory 仅在我 运行 一次整个套件(175 个测试)时发生,如果我 运行 单独设置每个测试集,则不会出现此问题。
  2. 我尝试使用在每个场景 运行ning 之后调用的 System.gc(),但仍然观察到 OutOfmemory 异常。
  3. 每次我 运行 在不同的测试脚本上都会出现异常,并且在特定功能/测试脚本上不一致。
  4. 整个应用程序使用的位图已经压缩,所以不确定这是否与图像大小有关。
  5. 下面是最近运行的日志:

    java.lang.Thread.run(Thread.java:818) 01-2614: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:支持TA~ 01-2614:42:45.180 4265-4317/? E/ContactsProvider_EventLog:刷新缓冲区到文件 cnt:3 大小:0Kb 持续时间:39ms lastUpdatedAfter:180367ms 01-26 14:42:52.510 3476-3476/? E/MotionRecognitionService:支持TA~ 01-26 14:42:55.320 446-454/? E/System: 终结器抛出未捕获的异常 01-26 14:42:56.900 446-454/? E/System:java.lang.OutOfMemoryError:尝试抛出 OutOfMemoryError 时抛出 OutOfMemoryError;没有可用的堆栈跟踪 01-2614:42:56.910 446-1088/? E/CrashReporting:ParseCrashReporting 捕获了 com.capitalone.mobilebanking.dev.debug 的 OutOfMemoryError 异常。建筑报告。 01-26 14:42:56.910 446-18726/? E/CrashReporting:ParseCrashReporting 捕获了 com.capitalone.mobilebanking.dev.debug 的 OutOfMemoryError 异常。建筑报告。 01-26 14:42:56.910 446-446/? E/MonitoringInstrumentation:遇到异常:Thread[main,5,main]。将线程状态转储到峡湾的输出和固定。 java.lang.OutOfMemoryError:在 OOM 之前无法分配具有 3960 个空闲字节和 3KB 的 40 字节分配 在 android.view.View.buildDrawingCacheImpl(View.java:16723) 在 android.view.View.buildDrawingCache(View.java:16625) 在 android.view.View.draw(View.java:17231) 在 android.view.ViewGroup.drawChild(ViewGroup.java:3921) 在 android.view.ViewGroup.dispatchDraw(ViewGroup.java:3711) 在 android.view.View.buildDrawingCacheImpl(View.java:16759) 在 android.view.View.buildDrawingCache(View.java:16625) 在 android.view.View.updateDisplayListIfDirty(View.java:16445) 在 android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3905) 在 android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3885) 在 android.view.View.updateDisplayListIfDirty(View.java:16424) 在 android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3905) 在 android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3885) 在 android.view.View.updateDisplayListIfDirty(View.java:16424) 在 android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3905) 在 android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3885) 在 android.view.View.updateDisplayListIfDirty(View.java:16424) 在 android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3905) 在 android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3885) 在 android.view.View.updateDisplayListIfDirty(View.java:16424) 在 android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3905) 在 android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3885) 在 android.view.View.updateDisplayListIfDirty(View.java:16424) 在 android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3905) 在 android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3885) 在 android.view.View.updateDisplayListIfDirty(View.java:16424) 在 android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3905) 在 android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3885) 在 android.view.View.updateDisplayListIfDirty(View.java:16424) 在 android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3905) 在 android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3885) 在 android.view.View.updateDisplayListIfDirty(View.java:16424) 在 android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3905) 在 android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3885) 在 android.view.View.updateDisplayListIfDirty(View.java:16424) 在 android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3905) 在 android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3885) 在 android.view.View.updateDisplayListIfDirty(View.java:16424) 在 android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:325) 在 android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:331) 在 android.view.ThreadedRenderer.draw(ThreadedRenderer.java:366) 在 android.view.ViewRootImpl.draw(ViewRootImpl.java:3134) 在 android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2933) 在 android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2522) 在 android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1437) 在 android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7397) 在 android.view.Choreographer$CallbackRecord.run(Choreographer.java:920) 在 android.view.Choreographer.doCallbacks(Choreographer.java:695) 在 android.view.Choreographer.doFrame(Choreographer.java:631) 在 android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:906) 在 android.os.Handler.handleCallback(Handler.java:739) 在 android.os.Handler.dispatchMessage(Handler.java:95) 在 android.os.Looper.loop(Looper.java:158) 在 android.app.ActivityThread.main(ActivityThread.java:7224) 在 java.lang.reflect.Method.invoke(本机方法) 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120) 01-26 14:42:56.910 446-18726/? E/AndroidRuntime:致命异常:IntentService[AlertSubscriptionService] 进程:com.capitalone.mobilebanking.dev.debug,PID:446 java.lang.OutOfMemoryError: 尝试抛出 OutOfMemoryError 时抛出 OutOfMemoryError;没有可用的堆栈跟踪 01-2614:42:56.910 446-1088/? E/CrashReporting: 崩溃处理异常 java.lang.OutOfMemoryError: 在 OOM 之前无法分配具有 3928 个空闲字节和 3KB 的 4092 字节分配 在 java.lang.AbstractStringBuilder.enlargeBuffer(AbstractStringBuilder.java:95) 在 java.lang.AbstractStringBuilder.append0(AbstractStringBuilder.java:146) 在 java.lang.StringBuffer.append(StringBuffer.java:219) 在 java.util.regex.Matcher.appendTail(Matcher.java:285) 在 java.util.regex.Matcher.replaceAll(Matcher.java:321) 在 gherkin.formatter.PrettyFormatter.indent(PrettyFormatter.java:469) 在 gherkin.formatter.PrettyFormatter.printError(PrettyFormatter.java:385) 在 gherkin.formatter.PrettyFormatter.printSteps(PrettyFormatter.java:133) 在 gherkin.formatter.PrettyFormatter.replay(PrettyFormatter.java:121) 在 gherkin.formatter.PrettyFormatter.eof(PrettyFormatter.java:421) 在 java.lang.reflect.Method.invoke(本机方法) 在 cucumber.runtime.Utils$1.call(Utils.java:34) 在 cucumber.runtime.Timeout.timeout(Timeout.java:13) 在 cucumber.runtime.Utils.invoke(Utils.java:30) 在 cucumber.runtime.RuntimeOptions$1.invoke(RuntimeOptions.java:243) 在 java.lang.reflect.Proxy.invoke(Proxy.java:393) 在 $Proxy11.eof(来源不明) 在 cucumber.runtime.model.CucumberFeature.run(CucumberFeature.java:165) 在 cucumber.runtime.android.CucumberExecutor.execute(CucumberExecutor.java:113) 在 cucumber.api.android.CucumberInstrumentationCore.start(CucumberInstrumentationCore.java:88) 在 com.capitalone.mobilebanking.espressoTests.Instrumentation.onStart(Instrumentation.java:133) 在 android.app.Instrumentation

我在开始 运行 同时进行 300 多项 Espresso 测试时遇到了同样的问题。 显然,每次测试后内存都没有清除导致OOM错误(OutOfMemoryError)。

为了解决这个问题,我开始使用 Android Test Orchestrator,它为您的测试环境提供以下好处:

  • 最小共享状态。每个测试 运行s 在其自己的 Instrumentation 中 实例。因此,如果您的测试共享应用程序状态,那么大部分 共享状态从您设备的 CPU 或内存中删除 测试。
  • 要在之后从设备的 CPU 和内存中删除所有共享状态 每次测试,使用 clearPackageData 标志。
  • 崩溃是孤立的。即使一个测试崩溃了,它也只会失败 它自己的 Instrumentation 实例,所以你套件中的其他测试 仍然 运行.

我在项目构建 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'
}