I am trying to enable proguard on my android tests. But I am facing a strange problem:
java.lang.NoSuchMethodError: No static method deleteRecursively(Ljava/io/File;)Z in class Lkotlin/io/FilesKt; or its super classes (declaration of 'kotlin.io.FilesKt' appears in /data/app/org.walleth.offline-BAciL8erjxU-sHGjQe6uQg==/base.apk!classes2.dex)
at org.ligi.trulesk.RulesKt.doBefore(Rules.kt:82)
at org.ligi.trulesk.RulesKt.access$doBefore(Rules.kt:1)
at org.ligi.trulesk.TruleskIntentRule.beforeActivityLaunched(Rules.kt:58)
at android.support.test.rule.ActivityTestRule.launchActivity(ActivityTestRule.java:351)
at android.support.test.rule.ActivityTestRule$ActivityStatement.evaluate(ActivityTestRule.java:525)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at android.support.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
at android.support.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:384)
at org.ligi.trulesk.AppReplacingRunnerBase.onStart(AppReplacingRunnerBase.kt:19)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2145)
Proguard on the release build works - not sure why it is so aggressive on android tests. Ideally the instrumentation classes would not be removed at all.
I think core issue is that androidTest is a different compilation unit. app/src/androidTest is assembled into app-debug-androidTest.apk while app/src/main is assembled into app-debug.apk. And so Proguard during assembleDebug neither see no includes app/src/androidTest into building "tree shaking" usage graph because it is not available on the classpath. Practically, it means that application code which is referenced in tests only is being stipped out.
This topic correlates with "Should I change visibility from private to public just for the test access?" dilema. Depending on what kind of tests you are writing you may consider to:
release.apkUnfortunately, I don't know any auto-magic solution at the moment (similar to all-open plugin). But it is possible to resolve missing methods issue in a case-by-case way.
buildTypes {
debug {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt', 'proguard-project-ext.txt'
testProguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-test-project.txt'
}
}
proguard-project.txt - configuration for app/src/main and it's implementation dependenciesproguard-project-ext.txt - configuration for app/src/main which contains -keep instructions for every method/field used in tests only which was "falsely" removed by proguard. I prefer to keep it separately, to conditionally remove when publishing to google playproguard-test-project.txt - configuration for app/src/androidTest and it's androidTestImplementation dependencies. Typically contains -dontwarn net.bytebuddy.** and etc. Although note, that test apk doesn't support multidex so it is possible to hit 65k limit method by including too many dependencies.Check android/platform/tools/base/studio-master-dev/./build-system/integration-test/test-projects/minify for the implementation reference.
test builds are by default always debug builds - even when setting a testBuildType, this has to have config initWith debug, which hints for a whole other mis-configuration. sorry for not providing the expected answer, but this mis-configuration is based upon a certain mis-conception. I'd suggest to disable the obfuscation, because it's rather pointless in this case, because this package won't ever be distributed. it might not even be possible to define ProGuard rules for the test application (which is a package on it's own). this behavior is "by design", caused by working against the test framework... because the test application will not know about the class/method obfuscation mapping of the other one application package - and therefore the chances are rather slim, that this could ever work out.
Firebase Test Lab Robo UX Test is the most similar to what is effectivly being demanded.