You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

启用R8后无法运行Android Instrumentation测试求助

启用R8后UI测试抛出ClassNotFoundException找不到自定义TestRunner

应用启用R8后运行正常,但禁用R8时能正常执行的UI测试,启用后报错:

Caused by: java.lang.ClassNotFoundException: Didn't find class "com.myapp.staff.CustomTestRunner"

BuildType配置

buildTypes{
    ...
    create("instrumentedTest") {
        isMinifyEnabled = true
        isShrinkResources = false
        extra.apply{
            set("enableCrashlytics", false)
        }
        manifestPlaceholders["crashlyticsCollectionEnabled"] = false
        configure<CrashlyticsExtension> {
            mappingFileUploadEnabled = false
        }

        proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
        testProguardFiles("proguard-test-rules.pro")
    }
}

完整报错栈

java.lang.RuntimeException: Unable to instantiate instrumentation ComponentInfo{com.myapp.test/com.myapp.FCBTestRunner}: java.lang.ClassNotFoundException: Didn't find class "com.myapp.FCBTestRunner" on path: DexPathList[[zip file "/system/framework/android.test.runner.jar", zip file "/system/framework/android.test.mock.jar", zip file "/system/framework/android.test.base.jar", zip file "/data/app/~~ot6m2KJbJHL_jYouR4mQ7A==/com.myapp.test-RvSjUeMRc0WaoKaPWNYuvA==/base.apk", zip file "/data/app/~~y1oGNjg7y-o2Lyq2z1RnqA==/com.myapp-gxOR-I3OFZEffP9SJyjDEg==/base.apk"],nativeLibraryDirectories=[/system/lib64, /system/system_ext/lib64, /system/product/lib64]]

已做排查

  • 检查映射文件,确认CustomTestRunner未被混淆:
    # {"id":"sourceFile","fileName":"FCBTestRunner.kt"}
        0:0:void <clinit>() -> <clinit>
        8:8:void <init>() -> <init>
        14:14:android.app.Application newApplication(java.lang.ClassLoader,java.lang.String,android.content.Context) -> newApplication
    
  • 用APK Analyzer检查androidTest.apk,CustomTestRunner确实存在于com/myapp/staff目录下
  • 在testProguardFiles中添加-dontobfuscate禁用混淆
  • 修改testProguardFiles配置为:
    testProguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro", "proguard-test-rules.pro")
    

以上操作后问题仍未解决,求解决方案。


解决方案尝试

1. 明确保留TestRunner类及相关依赖

R8的代码收缩可能在未明确规则时移除测试类,在proguard-test-rules.pro中添加:

# 保留自定义TestRunner
-keep public class com.myapp.staff.CustomTestRunner
-keep public class com.myapp.FCBTestRunner

# 保留TestRunner的父类及构造方法
-keep class androidx.test.runner.AndroidJUnitRunner {
    public <init>();
}
-keepclassmembers class com.myapp.staff.CustomTestRunner {
    public <init>();
}
-keepclassmembers class com.myapp.FCBTestRunner {
    public <init>();
}

2. 关闭测试代码的R8混淆/收缩

在instrumentedTest构建类型中,单独关闭测试代码的minify:

create("instrumentedTest") {
    // ... 原有配置
    androidTest {
        minifyEnabled = false
    }
}

或者直接禁用测试的R8处理:

android {
    testOptions {
        androidTest {
            isMinifyEnabled = false
        }
    }
}

3. 确保TestRunner在主Dex中

如果测试APK启用了多Dex,需保证TestRunner被包含在主Dex里,在proguard-test-rules.pro添加:

-dontpreverify
-keep public class com.myapp.staff.CustomTestRunner
-keep public class com.myapp.FCBTestRunner
# 强制将这些类放入主Dex
-maindexclasses com/myapp/staff/CustomTestRunner.class com/myapp/FCBTestRunner.class

4. 彻底清理缓存后重建

执行以下命令清除Gradle缓存并重新构建:

./gradlew clean
./gradlew assembleInstrumentedTest
./gradlew connectedInstrumentedTest

5. 核对包名与清单配置

报错中找不到的是com.myapp.FCBTestRunner,但你提到的是com.myapp.staff.CustomTestRunner,确认:

  • 测试清单中声明的Instrumentation类是否为FCBTestRunner
  • 两个类是否为同一类的不同包名/别名,确保所有相关类都被添加到ProGuard规则中

内容的提问来源于stack exchange,提问作者Khoa Chau

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 07:47:34