启用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
相关产品推荐
相关产品推荐

