Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OutOfMemory issue while running espresso tests in Android

I've been facing this issue (OutOfMemory) while running my espresso test suite on Kitkat and Lollipop devices. The suite runs perfectly fine on Marshmallow device. Below are more details and I would really appreciate if I could get any help in identifying the root cause of this issue. Below are more details :

  1. OutofMemory occurs only when I run entire suite at once (175 tests) and the issue doesn't occur if I run each test set individually.
  2. I tried to use System.gc() that is called after running every scenario, but still observed the OutOfmemory exception.
  3. The exception occurs on different test script everytime I run and is not consistent on particular feature / test script.
  4. The bitmaps used across the app are already compressed,so not sure if it has to do with the size of the images.
  5. Below is the log of the recent run :

    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 caught a OutOfMemoryError exception for com.capitalone.mobilebanking.dev.debug. Building report. 01-26 14:42:56.910 446-18726/? E/CrashReporting: ParseCrashReporting caught a OutOfMemoryError exception for com.capitalone.mobilebanking.dev.debug. Building report. 01-26 14:42:56.910 446-446/? E/MonitoringInstrumentation: Exception encountered by: Thread[main,5,main]. Dumping thread state to outputs and pining for the fjords. java.lang.OutOfMemoryError: Failed to allocate a 40 byte allocation with 3960 free bytes and 3KB until OOM 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.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.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:325) at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:331) at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:366) at android.view.ViewRootImpl.draw(ViewRootImpl.java:3134) at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2933) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2522) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1437) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7397) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:920) at android.view.Choreographer.doCallbacks(Choreographer.java:695) at android.view.Choreographer.doFrame(Choreographer.java:631) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:906) at android.os.Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:158) at android.app.ActivityThread.main(ActivityThread.java:7224) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120) 01-26 14:42:56.910 446-18726/? E/AndroidRuntime: FATAL EXCEPTION: IntentService[AlertSubscriptionService] Process: com.capitalone.mobilebanking.dev.debug, PID: 446 java.lang.OutOfMemoryError: OutOfMemoryError thrown while trying to throw OutOfMemoryError; no stack trace available 01-26 14:42:56.910 446-1088/? E/CrashReporting: Handling exception for crash java.lang.OutOfMemoryError: Failed to allocate a 4092 byte allocation with 3928 free bytes and 3KB until OOM at java.lang.AbstractStringBuilder.enlargeBuffer(AbstractStringBuilder.java:95) at java.lang.AbstractStringBuilder.append0(AbstractStringBuilder.java:146) at java.lang.StringBuffer.append(StringBuffer.java:219) at java.util.regex.Matcher.appendTail(Matcher.java:285) at java.util.regex.Matcher.replaceAll(Matcher.java:321) at gherkin.formatter.PrettyFormatter.indent(PrettyFormatter.java:469) at gherkin.formatter.PrettyFormatter.printError(PrettyFormatter.java:385) at gherkin.formatter.PrettyFormatter.printSteps(PrettyFormatter.java:133) at gherkin.formatter.PrettyFormatter.replay(PrettyFormatter.java:121) at gherkin.formatter.PrettyFormatter.eof(PrettyFormatter.java:421) at java.lang.reflect.Method.invoke(Native Method) at cucumber.runtime.Utils$1.call(Utils.java:34) at cucumber.runtime.Timeout.timeout(Timeout.java:13) at cucumber.runtime.Utils.invoke(Utils.java:30) at cucumber.runtime.RuntimeOptions$1.invoke(RuntimeOptions.java:243) at java.lang.reflect.Proxy.invoke(Proxy.java:393) at $Proxy11.eof(Unknown Source) at cucumber.runtime.model.CucumberFeature.run(CucumberFeature.java:165) at cucumber.runtime.android.CucumberExecutor.execute(CucumberExecutor.java:113) at cucumber.api.android.CucumberInstrumentationCore.start(CucumberInstrumentationCore.java:88) at com.capitalone.mobilebanking.espressoTests.Instrumentation.onStart(Instrumentation.java:133) at android.app.Instrumentation

like image 322
Darshan Avatar asked Jan 29 '17 04:01

Darshan


People also ask

How do I fix out of memory error in Android Studio?

If you haven't yet encountered an OOM in your Android application, you will in the near future. Memory leaks cause the OutOfMemoryError in Android. To eliminate the OutOfMemoryError, you must first eliminate memory leaks from your Android application.

What is Espresso UI Test?

Espresso is an open source android user interface (UI) testing framework developed by Google. The term Espresso is of Italian origin, meaning Coffee. Espresso is a simple, efficient and flexible testing framework.

What is Oom (out of memory) error while running test cases?

There we can face an issue of OOM (Out Of Memory) error while running test cases. Basically, when running multiple test cases one after another, the heap size of the device continuously increases, and after some point, it may cause an OOM error.

How to fix OutOfMemoryError in Android app?

If you haven't seen any OOM in your Android application, then you are going to have one in future. The OutOfMemoryError comes in Android due to memory leaks. So, in order to remove the OutOfMemoryError, you need to remove memory leaks from your Android application.

What is an oom error in android testing?

Basically, when running multiple test cases one after another, the heap size of the device continuously increases, and after some point, it may cause an OOM error. Applying Android Test Orchestrator from scratch in our projects increased the reliability of our automated test suites.

What is espresso testing?

Verifying the application manually whether it works or not is a time taking and tiring process, but using espresso we can write automated tests that run fast and scale well. Espresso is an automated user interface testing framework for Android, developed by Google in 2013.


1 Answers

I had the same issue when I started running more than 300 Espresso tests at once. Apparently, the memory is not cleared after each test which caused the OOM Error (OutOfMemoryError).

To fix the issue, I started using the Android Test Orchestrator which offers the following benefits for your testing environment:

  • Minimal shared state. Each test runs in its own Instrumentation instance. Therefore, if your tests share app state, most of that shared state is removed from your device's CPU or memory after each test.
  • To remove all shared state from your device's CPU and memory after each test, use the clearPackageData flag.
  • Crashes are isolated. Even if one test crashes, it takes down only its own instance of Instrumentation, so the other tests in your suite still run.

I added the Android Test Orchestrator in my project build gradle file to fix the issue:

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'
}
like image 190
ZakariaBK Avatar answered Oct 28 '22 16:10

ZakariaBK