Firebase Test Lab fails when using ProGuard + Dagger

别来无恙 提交于 2019-12-11 06:50:00

问题


Instrumented tests do pass on local emulators and physical devices but fail on Firebase Test Lab, when the following conditions are met:

  • ProGuard is enabled for the debug builds;
  • There are both Dagger and Espresso dependencies.

FTL shows different test issues:

1) In case with APIs 26-28 it shows either Instrumentation run failed due to 'java.lang.NoClassDefFoundError' or Instrumentation run failed due to 'Process crashed.'

Exception stacktrace looks like this, it's not always shown in Firebase but is always present in logcat:

Rejecting re-init on previously-failed class java.lang.Class<androidx.test.espresso.core.internal.deps.dagger.internal.Factory>:
java.lang.NoClassDefFoundError: Failed resolution of: Ljavax/inject/Provider;

FATAL EXCEPTION: Instr: androidx.test.runner.AndroidJUnitRunner
Process: com.example.debug, PID: 11425
java.lang.NoClassDefFoundError: Failed resolution of: Ljavax/inject/Provider;
    at java.lang.Class.classForName(Native Method)
    at java.lang.Class.forName(Class.java:453)
    at androidx.test.internal.runner.TestLoader.doCreateRunner(TestLoader.java:72)
    at androidx.test.internal.runner.TestLoader.getRunnersFor(TestLoader.java:104)
    at androidx.test.internal.runner.TestRequestBuilder.build(TestRequestBuilder.java:789)
    at androidx.test.runner.AndroidJUnitRunner.buildRequest(AndroidJUnitRunner.java:544)
    at androidx.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:387)
    at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2145)
Caused by: java.lang.ClassNotFoundException: Didn't find class "javax.inject.Provider" on path: DexPathList[[zip file "/system/framework/android.test.runner.jar", zip file "/system/framework/android.test.mock.jar", zip file "/data/app/com.example.debug.test-9kvw--JgNKzmuQurRdDbCQ==/base.apk", zip file "/data/app/com.example.debug-sz-oCUGs05zlEadCzyqsDA==/base.apk"],nativeLibraryDirectories=[/data/app/com.example.debug.test-9kvw--JgNKzmuQurRdDbCQ==/lib/arm64, /data/app/com.example.debug-sz-oCUGs05zlEadCzyqsDA==/lib/arm64, /system/lib64]]
    at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:134)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
    ... 8 more

2) I also ran one test on API 21 which only had one NoClassDefFoundError in the logs. However, this exception is also present on APIs 26-28, but is a part of the exception shown above. Maybe there's just some difference between how it's logged on different API levels.

java.lang.NoClassDefFoundError: androidx.test.espresso.core.internal.deps.dagger.internal.Factory

FATAL EXCEPTION: Instr: androidx.test.runner.AndroidJUnitRunner
Process: com.example.debug, PID: 5691
java.lang.NoClassDefFoundError: androidx.test.espresso.core.internal.deps.dagger.internal.Factory
    at java.lang.Class.classForName(Native Method)
    at java.lang.Class.forName(Class.java:308)
    at androidx.test.internal.runner.TestLoader.doCreateRunner(Unknown Source)
    at androidx.test.internal.runner.TestLoader.getRunnersFor(Unknown Source)
    at androidx.test.internal.runner.TestRequestBuilder.build(Unknown Source)
    at androidx.test.runner.AndroidJUnitRunner.buildRequest(Unknown Source)
    at androidx.test.runner.AndroidJUnitRunner.onStart(Unknown Source)
    at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1837)

Some relevant lines from build.gradle configuration:

android {
  defaultConfig {
    testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
  }

  buildTypes {
    debug {
      minifyEnabled true
      useProguard true
      proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules-debug.pro'
      testProguardFile 'proguard-rules-test.pro'
    }
  }
}

dependencies {
  testImplementation 'junit:junit:4.12'

  androidTestImplementation 'androidx.test:core:1.0.0-beta01'
  androidTestImplementation('androidx.test.espresso:espresso-core:3.1.0-beta01') {
    //  exclude module: 'javax.inject' - Exclusion doesn't help
  }
  // androidTestImplementation 'javax.inject:javax.inject:1' - Inclusion doesn't help either
  androidTestImplementation('androidx.test.ext:junit:1.0.0-beta01') {
    exclude group: "org.junit"
  }
  androidTestImplementation 'androidx.test:runner:1.1.0-beta01'
  androidTestImplementation 'androidx.test:rules:1.1.0-beta01'
  androidTestImplementation 'org.mockito:mockito-android:2.22.0'

  implementation 'com.google.dagger:dagger:2.16'
  kapt 'com.google.dagger:dagger-compiler:2.16'
}

proguard-rules-test.pro:

-ignorewarnings
-dontshrink
-dontoptimize
-dontobfuscate

Upon disabling ProGuard or removing Dagger dependency, tests start to pass on FTL.


回答1:


So I contacted Firebase support and got an embarrassingly simple solution.
Add the following rule to the proguard-rules-debug.pro

-keep class javax.inject.** { *; }

It's still not clear why this problem doesn't occur while testing locally.
But at least this solution works.



来源:https://stackoverflow.com/questions/52759473/firebase-test-lab-fails-when-using-proguard-dagger

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!