Run instrumentation tests with minified applications https://issuetracker.google.com/issues/137671763
We're going to run instrumentation tests along with production (minified) application. We want to cover all cases (including incorrect proguard (r8) configurations) and test exactly the same APK, that will be released to our users.
But now we have several issues mostly about inconsistent between methods from proguarded production APK and method references from test APK.
Right now I want to consider mismatching between proguarded external library inside target application (in that case kotlin standard library) and references to it from test application issue.
We have application, that has kotlin standard library as dependency. That allows us to use it from test application as well because of shared classpath.
I got from that conversation (https://issuetracker.google.com/issues/136284002), that all renames from target application also should be applied to test application by applying mappings feature. It works well, when we use renamed classes exactly from target application inside test application. But it doesn't work for renamed classes from external dependencies inside target application, that we're trying to use in our test application.
Test application still has references to original (not proguarded) methods. Looks like apply mappings feature doesn't work well for external dependencies.
- Clone project:
git clone https://github.com/dimorinny/r8-external-dependencies-mappings-instrumentation-tests
- Build test and target APKs
./gradlew app:assembleAndroidTest
- Open target APK (
app/build/outputs/apk/release/app-release-unsigned.apk
), and you will able to see, that kotlin standard library has been proguarded (renamed), becauseKotlinClassWithMethods
uses proguarded (renamed) version of methodsemptyList()
andsetOf()
and also all class references.
- Open test APK (
app/build/outputs/apk/androidTest/release/app-release-androidTest.apk
), and you will able to see thatKotlinClassWithMethodsInsideTestModule
uses full named (not proguarded) kotlin standard library names:
-
Sign APKs by
jarsigner
-
Run instrumentation tests using command:
adb shell am instrument -w -r -e debug false -e class 'com.dimorinny.proguard.KotlinClassWithMethodsInsideTestModule#useAppContext' com.dimorinny.proguard.test/android.support.test.runner.AndroidJUnitRunner
As a result you will have a exception:
java.lang.NoClassDefFoundError: Failed resolution of: Lkotlin/collections/CollectionsKt;
at com.dimorinny.proguard.KotlinClassWithMethodsInsideTestModule.method1(KotlinClassWithMethodsInsideTestModule.kt:4)
at com.dimorinny.proguard.ExampleInstrumentedTest.useAppContext(ExampleInstrumentedTest.java:19)
at java.lang.reflect.Method.invoke(Native Method)
...
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1853)
Applying mappings must be works for external dependencies. Exactly in this case, in test application we should have proguarded (renamed) references to kotlin standard library.