Gradle игнорирует testProguardFile при запуске инструментария Android
Я пытаюсь запустить инструментальные тесты на тип сборки выпуска. Моя установка выглядит следующим образом:
Android Studio - 3.4.1
Android Gradle Plugin - 3.4.1
Gragle - 5.4.1
R8 - Enabled (default)
Соответствующий фрагмент build.gradle:
testBuildType "release"
buildTypes {
release {
proguardFiles fileTree(dir: 'vendor', include: ['*.pro']).asList().toArray()
debuggable true
minifyEnabled true
shrinkResources true
signingConfig signingConfigs.release
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
testProguardFile 'proguard-rules-test.pro'
testCoverageEnabled false
}
}
Содержание proguard-rules-test.pro (для тестовых целей):
-keep public class ** { *; }
Запуск любого инструментария приводит к следующему исключению времени выполнения:
com.MYAPP.debug E/InstrumentationResultPrinter: Failed to mark test No Tests as finished after process crash
com.MYAPP.debug E/MonitoringInstr: Exception encountered by: Thread[main,5,main]. Dumping thread state to outputs and pining for the fjords.
java.lang.NoSuchMethodError: No virtual method setAppComponent(L/com/MYAPP/injection/AppComponent;)V in class L/com/MYAPP/data/common/MyApplication$Companion; or its super classes (declaration of 'com.MYAPP.data.common.MyApplication$Companion' appears in /data/app/com.MYAPP.debug-o3QrzyIOGC0Ko3XRS2fcxQ==/base.apk)
at com.MYAPP.base.TestMyApplication.h(TestMyApplication.kt:20)
at com.MYAPP.data.common.MyApplication.onCreate(MyApplication.kt:126)
(TestMyApplication расширяет MyApplication и вызывается AndroidJUnitRunner)
Перемещение строки -keep из proguard-rules-test.pro в основной файл правил Proguard позволяет без проблем запускать и проходить тесты.
Есть идеи?
2 ответа
Боролся с этим пару дней, и кажется, что по какой-то причине последние версии gradle/proGuard игнорируют этот параметр. (
Нашел действительно чистый и простой способ сделать это, используя некоторую условную логику внутри вашего релиза.
Ниже версия в kotlin dsl, поэтому
getByName("release") {
signingConfig = signingConfigs.getByName("release")
isDebuggable = false
// any other release config as normal
isMinifyEnabled = !gradle.startParameter.taskNames.any { it.contains("AndroidTest") }
proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro")
}
Надеюсь понятно, но если нет, то
Подтверждено, что это по-прежнему минимизирует выпуск apk, и теперь любая минимизация для тестового apk полностью отключена, и все модульные тесты теперь работают нормально на выпуске apk.
Это может быть неочевидно из ответа sgjesse, но это происходит в двух разных местах. Задачи для запуска инструментальных тестов на минифицированном вводе примерно следующие:
...
задача compileDebugWithJavaC задача
задача compileClassesAndResourcesWithR8ForDebug
задача compileDebugTestWithJavaC
задача compileClassesAndResourcesWithR8ForDebugTest
В приведенных выше задачах 1. и 2. компилирует ваше приложение и оптимизирует его с помощью R8, 3. и 4. компилирует ваши тесты и компилирует тесты с помощью R8, имея исходное приложение на пути к библиотеке.
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' применяются к 2. при компиляции приложения с R8.
testProguardFile 'proguard-rules-test.pro' применяется к тестам, когда вы компилируете тесты с R8. Это причина того, почему добавление правил хранения к "нормальным" файлам proguard работает, потому что вы добавляете их поздно.
Если вы хотите, чтобы правила применялись к вашему основному приложению при запуске отладки, просто добавьте конфигурацию отладки и добавьте туда еще один файл:
buildTypes{
debug {
..
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt', 'proguard-rules-test.pro'
}
Во всех случаях я не понимаю, почему вы "тестируете" свое мини-приложение, если добавляете -keep public class ** { *; }. Это в основном помешает R8 выполнять какие-либо оптимизации, поэтому вы можете тестировать без minifyEnabled. В идеале вы должны найти точки входа в свои тесты в своем приложении и только добавить их. Это, конечно, не так просто с сгенерированными классами-компаньонами в kotlin.