Gradle 在运行 Android 检测时忽略 testProguardFile

Posted

技术标签:

【中文标题】Gradle 在运行 Android 检测时忽略 testProguardFile【英文标题】:Gradle ignores testProguardFile when running Android instrumentation 【发布时间】:2019-10-16 21:01:21 【问题描述】:

我正在尝试在 release 构建类型上运行仪器测试。 我的设置如下:

android Studio - 3.4.1
Android Gradle Plugin - 3.4.1
Gragle - 5.4.1
R8 - Enabled (default)

相关build.gradle sn-p:

    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 规则文件中,使测试能够顺利运行并通过。

有什么想法吗?

【问题讨论】:

我很高兴听到您正在应用的发布版本上运行测试。然而,这可能会带来一些复杂性,我们正试图在 R8 中处理这些复杂性。现在,这里的问题似乎是主应用程序的优化正在删除测试所需的部分。为了确保插桩测试可以访问主应用程序的所需部分,您可以向应用程序添加保留规则,将测试入口点视为插桩测试的 api。你可以试试这样的:-keep class **.MyApplication* *; . 请在issuetracker.google.com/issues?q=componentid:326788 上提交错误,以便我们跟踪这些 R8 问题。该错误引用了 Kotlin 配套类,R8 可以对其进行优化,但如果插桩测试通过 MyApplication 的子类需要它,则优化可能会破坏插桩测试。 【参考方案1】:

从 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 中生成的伴生类那么容易。

【讨论】:

以上是关于Gradle 在运行 Android 检测时忽略 testProguardFile的主要内容,如果未能解决你的问题,请参考以下文章

忽略 Gradle 构建失败并继续构建脚本?

Android+git+hudson+gradle持续集成

gradle build 未检测到 build.gradle 中的 android ndkVersion

Android Studio - Proguard“保留”规则被忽略?

忽略gradle beta依赖项

如何在 gradle kts 中排除(忽略)android 构建变体