java - 项目库上的 Android Instrumented 单元测试
问题描述
我继承了一个由主应用程序和一个库组成的 Android 项目。我的目标是测试整个项目,所以我从库开始:首先我使用 JUnit 测试一些类/方法,编写我的库项目的测试应用程序/src/test/java(单元测试),同时生成一个Android Studio 的代码覆盖率报告。当我找到一个使用 Parcel 的类(来自 Android 框架)时,问题就来了,所以这次我必须在库项目中设置一个检测测试(app/src/androidTest/java)。
当我尝试运行仪器测试并插入 Android 设备时,我收到了以下消息:
Started running tests
Test running failed: Instrumentation run failed due to 'java.lang.ClassNotFoundException'
Empty test suite.
我不明白为什么“空测试套件”,而我的测试类中有几个 @Test 方法。我是否必须设置 Gradle 如何在测试期间链接主应用程序和库?也许我必须在主应用程序中移动我的所有测试?!
这是我对图书馆模块的 gradle:
apply plugin: 'com.android.library'
android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
defaultConfig {
minSdkVersion rootProject.ext.minSdkVersion
// Added for instrumental tests
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
javaCompileOptions {
annotationProcessorOptions {
arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]
}
}
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
debuggable true
testCoverageEnabled true
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
testOptions {
unitTests.returnDefaultValues = true
}
}
dependencies {
implementation "com.android.support:support-v4:$rootProject.supportLibraryVersion"
implementation "com.google.code.gson:gson:$rootProject.gsonVersion"
implementation "commons-io:commons-io:$rootProject.commonsioVersion"
// Dependencies for RxBinding
implementation 'com.jakewharton.rxbinding2:rxbinding:2.0.0'
// Dependencies for Rxjava2 and RxAndroid
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
implementation 'io.reactivex.rxjava2:rxjava:2.1.8'
// Dependencies for RxBinding
implementation 'com.jakewharton.rxbinding2:rxbinding:2.0.0'
// Dependencies for Retrofit
implementation 'com.squareup.retrofit2:retrofit:2.3.0'
implementation 'com.squareup.retrofit2:converter-simplexml:2.3.0'
implementation 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
implementation 'com.squareup.okhttp:okhttp:2.7.0'
// Dependencies for Room
// Room (use 1.1.0-alpha1 for latest alpha)
implementation 'android.arch.persistence.room:runtime:1.1.1'
implementation 'android.arch.persistence.room:rxjava2:1.1.1'
annotationProcessor "android.arch.persistence.room:compiler:1.1.1"
implementation "com.android.support:support-annotations:$rootProject.supportLibraryVersion"
implementation "org.apache.httpcomponents:httpcore:$rootProject.httpcoreVersion"
testImplementation 'junit:junit:4.12'
// // [Android Instrumented test]
androidTestImplementation 'junit:junit:4.12'
// androidTestImplementation 'androidx.test:runner:1.1.0'
// androidTestImplementation 'androidx.test:rules:1.1.0'
// // Optional -- Hamcrest library
androidTestImplementation 'org.hamcrest:hamcrest-library:1.3'
// // Optional -- UI testing with Espresso
// androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'
// // Optional -- UI testing with UI Automator
// androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0'
api files('libs/lifesense_ble_v3.3.7.jar')
api files('libs/MedPixel.jar')
}
和应用程序的:
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
buildToolsVersion '28.0.3'
defaultConfig {
applicationId "it.*******.********"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 2
versionName "1.0.2"
}
buildTypes {
release {
shrinkResources true
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
applicationIdSuffix ".debug"
debuggable true
}
}
lintOptions {
checkReleaseBuilds false
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation project(':..:Libraries:app')
implementation "com.android.support:support-v4:$rootProject.supportLibraryVersion"
implementation "com.google.code.gson:gson:$rootProject.gsonVersion"
implementation "commons-io:commons-io:$rootProject.commonsioVersion"
// Dependencies for ButterKnife
implementation 'com.jakewharton:butterknife:8.8.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
// Dependencies for Dagger
implementation 'com.google.dagger:dagger:2.11'
annotationProcessor 'com.google.dagger:dagger-compiler:2.11'
// Dependencies for RxBinding
implementation 'com.jakewharton.rxbinding2:rxbinding:2.0.0'
// Dependencies for Rxjava2 and RxAndroid
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
implementation 'io.reactivex.rxjava2:rxjava:2.1.8'
// Dependencies for Retrofit
implementation 'com.squareup.retrofit2:retrofit:2.3.0'
implementation 'com.squareup.retrofit2:converter-simplexml:2.3.0'
implementation 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
implementation 'com.squareup.okhttp:okhttp:2.7.0'
// Dependencies for Room
implementation 'android.arch.persistence.room:runtime:1.1.1'
// Dependencies for Roboelecttic
testImplementation 'org.robolectric:robolectric:3.6.1'
testImplementation 'junit:junit:4.12'
// Dependencies for Mockito
testImplementation 'org.mockito:mockito-core:2.7.22'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
androidTestImplementation 'com.squareup.retrofit2:retrofit-mock:2.0.0'
androidTestImplementation 'com.squareup.okhttp:mockwebserver:2.7.0'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'org.mockito:mockito-android:2.7.22'
}
configurations.all {
resolutionStrategy {
force "android.arch.core:runtime:1.1.1"
force "com.android.support:support-core-utils:28.0.0"
/*force "com.android.support:support-compat:28.0.0"*/
}
}
感谢关注!
解决方案
我遇到了同样的问题,不是Parcel
使用其他 android 组件,而是使用Context
.
对于这个问题,
空测试套件
您的仪器测试类必须使用 @RunWith(AndroidJUnit4.class)
.
关于库的代码覆盖率
最初我确实在app
. 但是编写库的InstrumentationTests
问题app
是,您将无法获得library
.
因此,我将其移InstrumentedTests
回library/androidTest
文件夹。经过大量研究,我找到了获得完整覆盖率报告的解决方案library
在您的图书馆build.gradle
文件中执行以下操作以获得覆盖
添加
apply plugin: 'jacoco'
启用测试覆盖率如下
android { buildTypes { debug { testCoverageEnabled true } } ... }
添加以下依赖项
androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test:rules:1.0.2'
我相信,对于您项目中的任何模块,如果androidTests
您的模块/库中有,就会有一个名为combinedTestReportDebug
.
您可以在Gradle
Android Studio 右上角垂直栏中的可用菜单中找到它。
Gradle menu > :your-library > Tasks > reporting > combinedTestReportDebug
或者
在您的Terminal
>中运行此命令./gradlew clean combinedTestReportDebug -p :your-library
测试完成后,您可以在以下位置找到覆盖率或失败的测试
对于失败的测试: your-library/build/reports/androidTests/connected/index.html
对于覆盖率报告: your-library/build/reports/coverage/debug/index.html
我希望这有帮助。
更新:
对不起,我忘了提到下面需要的步骤,因为如果不是,combinedTestReportDebug
将不可见。感谢@nicoabie。
在您的项目build.gradle
文件中,执行以下操作以使combinedTestReportDebug
任务在您的库 gradle 任务中可见。
buildscript {
repositories {
jcenter()
}
dependencies {
...
classpath 'com.vanniktech:gradle-android-junit-jacoco-plugin:0.13.0'
...
}
}
...
apply plugin: 'com.vanniktech.android.junit.jacoco'
推荐阅读
- windows - 有没有办法根据窗口样式计算最大化、最小化和关闭按钮的数量?
- python - 绘制成本函数并查看迭代中的每个 theta 值
- java - -source 1.6 不支持 lambda 表达式
- reactjs - 如何通过组件动态使用 REST API?
- python - 每当尝试使用以下代码下载视频时文件损坏
- javascript - 开玩笑找不到模块
- python - 使用python多次序列的线密度图
- mysql - 一个事务中的 INSERT 语句会阻塞另一个事务中的 DELETE 语句吗?
- java - 如何解决 SonarQube 对我的代码的投诉?
- javascript - JavaScript NodeJs 开放库