启用多索引的仪器测试随机失败
Instrumentation test fail randomly with multidexing enabled
在我的 android 应用程序中,我启用了多索引。该应用程序在模拟器上运行良好。我正在使用 robotium 来测试应用程序。但是当我执行仪器测试用例时,有时测试通过,但大多数情况下它们在系统重启后也会失败。通过和失败之间没有代码更改。
默认gradle配置:
android {
defaultConfig {
applicationId "com.example.androidapp"
minSdkVersion 16
targetSdkVersion 23
multiDexEnabled true
testInstrumentationRunner "com.android.test.runner.MultiDexTestRunner"
testProguardFile "proguard-test.txt"
}
}
同时为测试添加依赖项:
androidTestCompile fileTree(dir: 'libs', include:'robotium-solo-5.3.0.jar')
androidTestCompile ('com.android.support:multidex-instrumentation:1.0.1') {
exclude group: 'com.android.support', module: 'multidex' }
在 AndroidManifest.xml 中,我提到的应用程序标记为:
<application
android:name="StartupActivity"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" ...../>
我在 StartupActivity 中扩展了 "android.support.multidex.MultiDexApplication"。仪器测试用例下降的时间我得到以下错误:
INSTRUMENTATION_RESULT: shortMsg=java.lang.IllegalAccessError
INSTRUMENTATION_RESULT: longMsg=java.lang.IllegalAccessError: Class ref in pre-verified class resolved to unexpected implementation
INSTRUMENTATION_CODE: 0
logcat中的错误信息是:
W/dalvikvm﹕ Class resolved by unexpected DEX: Lcom/example/androidapp/StartupActivity;(0xa695df08):0x9910e000 ref [Landroid/support/multidex/MultiDexApplication;] Landroid/support/multidex/MultiDexApplication;(0xa695df08):0x99a2c000
W/dalvikvm﹕ (Lcom/example/androidapp/StartupActivity; had used a different Landroid/support/multidex/MultiDexApplication; during pre-verification)
W/dalvikvm﹕ Unable to resolve superclass of Lcom/example/androidapp/StartupActivity; (540)
W/dalvikvm﹕ Link of class 'Lcom/example/androidapp/StartupActivity;' failed
D/AndroidRuntime﹕ Shutting down VM
W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0xa628c288)
测试 class 看起来有点像:
public class HelloActivityTest extends ActivityInstrumentationTestCase2<HelloActivity> {
private Solo solo;
public HelloActivityTest() {
super(HelloActivityTest.class);
}
@Override
public void setUp() throws Exception {
setActivityInitialTouchMode(false);
solo = new Solo(getInstrumentation(), getActivity());
}
public void test1() {}
public void test2() {}
}
我是运行测试用例作为android测试。我无法理解是哪个依赖项扰乱了代码。除此之外,代码的随机失败是值得怀疑的。请帮忙。
同样找到了解决方法,就是设置dex验证和优化参数。您还可以将 dalvik.vm.dexopt-flags 设置为 v=n 以使框架通过 -Xverify:none -Xdexopt:verified 以禁用验证。
执行:
adb shell setprop dalvik.vm.dexopt-flags v=n,o=v
adb shell stop installd
adb shell start installd
执行命令后需要等待几秒钟。用 multidexing 进行 Instrumentation 测试 运行 顺利 post that.
如果您使用的是 1.4.0-beta3 以上的 gradle 插件。 Multi-Dex 支持已添加到 gradle 插件,这意味着 multidex
和 multidex-instrumentation
依赖项已包含在内,您无需明确指定它们。不幸的是,它在 Lollipop 之前的设备上似乎有问题,看起来 MultiDexApplication
的不同版本用于目标和测试应用程序。结果 Instrumentation 无法 运行 和 logcat 给你类似的东西:
W/dalvikvm: Class resolved by unexpected DEX: Lcom/example/dexproof/App;(0x43893f90):0x64d46000 ref [Landroid/support/multidex/MultiDexApplication;] Landroid/support/multidex/MultiDexApplication;(0x43893f90):0x5de01000
W/dalvikvm: (Lcom/example/dexproof/App; had used a different Landroid/support/multidex/MultiDexApplication; during pre-verification)
W/dalvikvm: Unable to resolve superclass of Lcom/example/dexproof/App; (457)
W/dalvikvm: Link of class 'Lcom/example/dexproof/App;' failed
E/AndroidRuntime: java.lang.IllegalAccessError: Class ref in pre-verified class resolved to unexpected implementation
解决方案是使用 1.3.1 gradle 插件并注意显式指定 multidex
和 multidex-instrumentation
(如果你也需要这个)相同版本的依赖项.您可能还想使用 AndroidJUnitRunner
,因为它具有内置的多 dex 支持。
欢迎给相关问题加注星标:https://code.google.com/p/android/issues/detail?id=194609
对于 gradle 插件 1.5.0,您可以在 build.gradle:
中使用此解决方法
// Workaround for Multidex bug in gradle-android-plugin
// Replace Multidex dependency with some dummy dependency to avoid dex problems
// @see https://code.google.com/p/android/issues/detail?id=194609
project.getConfigurations().all { config ->
if (config.name.contains("AndroidTest")) {
config.resolutionStrategy.eachDependency { DependencyResolveDetails details ->
if (details.requested.name == "multidex") {
details.useTarget("de.felixschulze.teamcity:teamcity-status-message-helper:1.2")
}
}
}
}
在我的 android 应用程序中,我启用了多索引。该应用程序在模拟器上运行良好。我正在使用 robotium 来测试应用程序。但是当我执行仪器测试用例时,有时测试通过,但大多数情况下它们在系统重启后也会失败。通过和失败之间没有代码更改。
默认gradle配置:
android {
defaultConfig {
applicationId "com.example.androidapp"
minSdkVersion 16
targetSdkVersion 23
multiDexEnabled true
testInstrumentationRunner "com.android.test.runner.MultiDexTestRunner"
testProguardFile "proguard-test.txt"
}
}
同时为测试添加依赖项:
androidTestCompile fileTree(dir: 'libs', include:'robotium-solo-5.3.0.jar')
androidTestCompile ('com.android.support:multidex-instrumentation:1.0.1') {
exclude group: 'com.android.support', module: 'multidex' }
在 AndroidManifest.xml 中,我提到的应用程序标记为:
<application
android:name="StartupActivity"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" ...../>
我在 StartupActivity 中扩展了 "android.support.multidex.MultiDexApplication"。仪器测试用例下降的时间我得到以下错误:
INSTRUMENTATION_RESULT: shortMsg=java.lang.IllegalAccessError
INSTRUMENTATION_RESULT: longMsg=java.lang.IllegalAccessError: Class ref in pre-verified class resolved to unexpected implementation
INSTRUMENTATION_CODE: 0
logcat中的错误信息是:
W/dalvikvm﹕ Class resolved by unexpected DEX: Lcom/example/androidapp/StartupActivity;(0xa695df08):0x9910e000 ref [Landroid/support/multidex/MultiDexApplication;] Landroid/support/multidex/MultiDexApplication;(0xa695df08):0x99a2c000
W/dalvikvm﹕ (Lcom/example/androidapp/StartupActivity; had used a different Landroid/support/multidex/MultiDexApplication; during pre-verification)
W/dalvikvm﹕ Unable to resolve superclass of Lcom/example/androidapp/StartupActivity; (540)
W/dalvikvm﹕ Link of class 'Lcom/example/androidapp/StartupActivity;' failed
D/AndroidRuntime﹕ Shutting down VM
W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0xa628c288)
测试 class 看起来有点像:
public class HelloActivityTest extends ActivityInstrumentationTestCase2<HelloActivity> {
private Solo solo;
public HelloActivityTest() {
super(HelloActivityTest.class);
}
@Override
public void setUp() throws Exception {
setActivityInitialTouchMode(false);
solo = new Solo(getInstrumentation(), getActivity());
}
public void test1() {}
public void test2() {}
}
我是运行测试用例作为android测试。我无法理解是哪个依赖项扰乱了代码。除此之外,代码的随机失败是值得怀疑的。请帮忙。
同样找到了解决方法,就是设置dex验证和优化参数。您还可以将 dalvik.vm.dexopt-flags 设置为 v=n 以使框架通过 -Xverify:none -Xdexopt:verified 以禁用验证。
执行:
adb shell setprop dalvik.vm.dexopt-flags v=n,o=v
adb shell stop installd
adb shell start installd
执行命令后需要等待几秒钟。用 multidexing 进行 Instrumentation 测试 运行 顺利 post that.
如果您使用的是 1.4.0-beta3 以上的 gradle 插件。 Multi-Dex 支持已添加到 gradle 插件,这意味着 multidex
和 multidex-instrumentation
依赖项已包含在内,您无需明确指定它们。不幸的是,它在 Lollipop 之前的设备上似乎有问题,看起来 MultiDexApplication
的不同版本用于目标和测试应用程序。结果 Instrumentation 无法 运行 和 logcat 给你类似的东西:
W/dalvikvm: Class resolved by unexpected DEX: Lcom/example/dexproof/App;(0x43893f90):0x64d46000 ref [Landroid/support/multidex/MultiDexApplication;] Landroid/support/multidex/MultiDexApplication;(0x43893f90):0x5de01000
W/dalvikvm: (Lcom/example/dexproof/App; had used a different Landroid/support/multidex/MultiDexApplication; during pre-verification)
W/dalvikvm: Unable to resolve superclass of Lcom/example/dexproof/App; (457)
W/dalvikvm: Link of class 'Lcom/example/dexproof/App;' failed
E/AndroidRuntime: java.lang.IllegalAccessError: Class ref in pre-verified class resolved to unexpected implementation
解决方案是使用 1.3.1 gradle 插件并注意显式指定 multidex
和 multidex-instrumentation
(如果你也需要这个)相同版本的依赖项.您可能还想使用 AndroidJUnitRunner
,因为它具有内置的多 dex 支持。
欢迎给相关问题加注星标:https://code.google.com/p/android/issues/detail?id=194609
对于 gradle 插件 1.5.0,您可以在 build.gradle:
中使用此解决方法// Workaround for Multidex bug in gradle-android-plugin
// Replace Multidex dependency with some dummy dependency to avoid dex problems
// @see https://code.google.com/p/android/issues/detail?id=194609
project.getConfigurations().all { config ->
if (config.name.contains("AndroidTest")) {
config.resolutionStrategy.eachDependency { DependencyResolveDetails details ->
if (details.requested.name == "multidex") {
details.useTarget("de.felixschulze.teamcity:teamcity-status-message-helper:1.2")
}
}
}
}