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, поэтому но, без сомнения, будет эквивалент Groovy при использовании обычного :

           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")
    }

Надеюсь понятно, но если нет, то в основном говорит НЕ МИНИФИЦИРОВАТЬ, если задача gradle, которая запустила сборку, где-то содержит «AndroidTest».

Подтверждено, что это по-прежнему минимизирует выпуск apk, и теперь любая минимизация для тестового apk полностью отключена, и все модульные тесты теперь работают нормально на выпуске apk.

Это может быть неочевидно из ответа sgjesse, но это происходит в двух разных местах. Задачи для запуска инструментальных тестов на минифицированном вводе примерно следующие:

...

  1. задача compileDebugWithJavaC задача

  2. задача compileClassesAndResourcesWithR8ForDebug

  3. задача compileDebugTestWithJavaC

  4. задача 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.

Другие вопросы по тегам