I am trying to get code coverage for my Android project using Espresso tests. However, Jacoco is giving me back a report saying that I don't cover anything. I made a demo app to highlight my problem and that is here.
If you don't want to go to Github to look at the project, here is the build.gradle file:
apply plugin: 'com.android.application'
apply plugin: 'jacoco'
android {
compileSdkVersion 22
buildToolsVersion "22.0.1"
defaultConfig {
applicationId "ninja.bryansills.jacocotest"
minSdkVersion 16
targetSdkVersion 22
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
packagingOptions {
exclude 'LICENSE.txt'
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
testCoverageEnabled true
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:22.1.1'
androidTestCompile 'com.android.support.test:runner:0.2'
androidTestCompile 'com.android.support.test:rules:0.2'
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.1'
}
Based on the issue pointed out by Ligol, here is what worked for me.
Added custom test runner in androidTest
package com.example;
import android.os.Bundle;
import android.support.test.runner.AndroidJUnitRunner;
import android.util.Log;
import java.lang.reflect.Method;
public class AndroidJacocoTestRunner extends AndroidJUnitRunner {
static {
System.setProperty("jacoco-agent.destfile", "/data/data/"+BuildConfig.APPLICATION_ID+"/coverage.ec");
}
#Override
public void finish(int resultCode, Bundle results) {
try {
Class rt = Class.forName("org.jacoco.agent.rt.RT");
Method getAgent = rt.getMethod("getAgent");
Method dump = getAgent.getReturnType().getMethod("dump", boolean.class);
Object agent = getAgent.invoke(null);
dump.invoke(agent, false);
} catch (Throwable e) {
Log.d("JACOCO", e.getMessage());
}
super.finish(resultCode, results);
}
}
Used this test runner in app/build.gradle
android{
...
defaultConfig {
....
testInstrumentationRunner "com.example.AndroidJacocoTestRunner"
}
}
Your problem might be related to this issue.
https://code.google.com/p/android/issues/detail?id=170607
I had the same problem on Samsung device, I did not change anything but changed to HTC device I started getting the coverage.ec Something seems to be fishy with JaCoCo Samsung device.
I advise everyone not to use a Samsung device while generating coverage reports. I tried everything to fix the 0 coverage issue and luckily changed my device to Redmi Note 5 Pro and voila the coverage starts showing.
On doing some research and reading some articles I found Samsung give less freedom to its user to use their products for testing. Though you can do the testing on Samsung devices after rooting them.
Related
I am new in Instrumentation testing. I am trying basic testing with AndroidJUnitRunner. Here is my gradle:
apply plugin: 'com.android.application'
android {
compileSdkVersion 24
buildToolsVersion "25.0.0"
defaultConfig {
applicationId "com.kaushik.mycart.ui"
minSdkVersion 15
targetSdkVersion 24
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
jackOptions.enabled true
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
..........................
..........................
testCompile 'junit:junit:4.12'
testCompile 'org.mockito:mockito-core:1.10.19'
androidTestCompile 'org.hamcrest:hamcrest-library:1.3'
}
Then I added a class named 'ProductListActivityTest' to test with AndroidJunitRunner. It is below:
package com.kaushik.myredmart.ui;
// all includes
#RunWith(AndroidJUnit4.class)
public class ProductListActivityTest {
#Rule
public ActivityTestRule<ProductListActivity> rule = new ActivityTestRule<>(ProductListActivity.class);
#Test
public void ensureListViewIsPresent() throws Exception {
ProductListActivity activity = rule.getActivity();
View viewByIdw = activity.findViewById(R.id.productListView);
assertThat(viewByIdw,notNullValue());
assertThat(viewByIdw, instanceOf(RecyclerView.class));
RecyclerView productListView = (RecyclerView) viewByIdw;
RecyclerView.Adapter adapter = productRecyclerView.getAdapter();
assertThat(adapter, instanceOf(ProductAdapter.class));
}
}
I have added no other file in 'androidTest'. I like to also mention that there is Application class file in my source code. Now every time I try to run the test, it is giving following error:
Started running tests
Test running failed: Instrumentation run failed due to 'java.lang.ClassNotFoundException'
Empty test suite.
Can anyone help me identifying the problem in my test code?
How are you running your tests?
If you are doing it from Android Studio:
Open Run menu -> Edit Configurations
Add a new Android Tests configuration
Choose a module
Add a specific instrumentation runner:
android.support.test.runner.AndroidJUnitRunner
From command-line via Gradle:
./gradlew connectedAndroidTest
I solved the problem. It is due to difference of Package names. I set all package name uniform and run again. It works. Thank you all for helping.
I have an Android project and I use Android Studio. In this project, I have the main app (cdmandroidclient) and the SDK (cdmsdk) which is the core lib.
I added recently a library built with Java 8 into my Android project. So I had to change a few things into my Gradle files :
apply plugin: 'com.android.application'
android {
compileSdkVersion 24
buildToolsVersion "24.0.1"
defaultConfig {
applicationId "com.mycompany.cdmandroidclient"
minSdkVersion 15
targetSdkVersion 24
versionCode 1
versionName "1.0"
jackOptions {
enabled true
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
minifyEnabled false
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
testCompile 'junit:junit:4.12'
compile project(path: ':cdmsdk')
compile 'com.android.support:appcompat-v7:24.2.0'
}
As you can see, I import into my app, the cdmsdk module, which is part of my project. Before using Jack, everything was fine.
Now, when I try to build the app I get errors for resolving dependencies of my module "cdmsdk" into my app "cdmandroidclient".
Exemple of an error :
Error:E:\Workspace\CDMAndroidClient\app\src\main\java\com\mycompany\cdmandroidclient\service\CdmService.java:16:
The import com.mycompany.cdmsdk.heartbeat.Security cannot be resolved
I don't understand what's happening, because the main app dependencies have not changed and still reference the SDK with :
compile project(path: ':cdmsdk')
The Gradle build fail as I said, during the task :app:compileDebugJavaWithJack
Any idea ? Thank you very much :) !
EDIT : It's the exact same thing as Javac and with Java 7... don't know what I've changed but my app can't use cdmsdk dependencies anymore ... wtf
I have some Android instrumentation tests with a custom test runner that all seemed to work fine until at some point after I upgraded to Android Studio 2.1, bumped up some library versions, and did some other things over time. Now, my tests don't run anymore with the dreaded Unable to find instrumentation info for: ComponentInfo{} that has been asked about on StackOverflow a million times already.
Upon further investigation, it seems like Android Studio simply doesn't compile my test code, which then means its code is never included, so it can't find the ComponentInfo for the test runner. I verified that by adding compile errors in my test code, which never cause any issues when I try to run a test.
Furthermore, the test code seems to be treated like non-test code in the syntax highlighter? As an example, the test runner imports android.support.test.runner.AndroidJUnitRunner, but runner is highlighted in red as if that library is missing (but it's in the gradle file as androidTestCompile). If I change that to compile, the syntax highlighter is happy. However, the test code shows up in the project view in yellow, like test code would.
I'm not sure what determines what Android Studio compiles for a test. The setup is straightforward. My file hierarchy is
app
+--src
+ +--main
+ | +--java
+ | +--com/package/files
+ |
+ +--androidTest
+ +--java
+ +--com/package/files
In other words, there's app/src/main/java/com/... and app/src/androidTest/java/com.... Both the main app and the tests use the same package.
build.gradle (relevant parts):
apply plugin: 'com.android.application'
android {
compileSdkVersion 'Google Inc.:Google APIs:23'
buildToolsVersion '24.0.0 rc3'
defaultConfig {
multiDexEnabled = true
applicationId 'com.package'
minSdkVersion 10
targetSdkVersion 23
versionCode 2
versionName '0.8a'
signingConfig signingConfigs.release
testInstrumentationRunner 'com.package.TestRunner'
}
buildTypes {
release {
signingConfig signingConfigs.release
}
debug {
signingConfig signingConfigs.release
}
}
productFlavors {
}
dexOptions {
javaMaxHeapSize "4g"
}
packagingOptions {
exclude 'META-INF/LICENSE'
exclude 'META-INF/LICENSE-FIREBASE.txt'
exclude 'META-INF/NOTICE'
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
lintOptions {
checkReleaseBuilds true
abortOnError true
}
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
androidTestCompile 'com.android.support.test:runner:0.5'
androidTestCompile 'com.android.support.test:rules:0.5'
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.1'
androidTestCompile 'com.android.support.test.espresso:espresso-intents:2.2'
androidTestCompile 'org.hamcrest:hamcrest-library:1.3'
androidTestCompile 'com.android.support:support-annotations:23.1.1'
compile 'com.android.support:appcompat-v7:23.1.1'
compile 'com.android.support:support-v4:23.1.1'
[...]
}
apply plugin: 'com.google.gms.google-services'
The run/debug configuration for the test is straightforward as well - it's an Android Test, the instrumentation runner is com.package.TestRunner. I tried cleaning/rebuilding many times.
The answer is so embarrassing that I shouldn't post it.
The "Build Variant" for all my modules was set to "Release", so none of the test stuff was compiled. Setting it to "Debug" took care of the problem. Would be nice if Android Studio was a bit more vocal about it, like warning about running tests while using the release shards.
I'm trying to implement a test class in Android Studio to make some test on a DBAdapter. Since I need to run the test on my mobile phone in order to use the database, I have created an Instrumentation Unit Test (cause I've tried to do it just with a Unit test but I need to use the database and so, and those are only run locally).
The problem is that when I try to run the test class, using my mobile phone as running device, the compiler throws the following error:
error: package org.junit does not exist
I've been looking for a solutione, but I found none.
This is my test class (just the skeleton):
import org.junit.Test;
import android.support.test.runner.AndroidJUnit4;
import static org.junit.Assert.*;
public class DbAdapterTest {
#Test
public void testCreateSeries() throws Exception {
}
}
And this one is the build.gradle script:
apply plugin: 'com.android.application'
android {
compileSdkVersion 23
buildToolsVersion "23.0.2"
defaultConfig {
applicationId "com.w2w.whattowatch"
minSdkVersion 15
targetSdkVersion 23
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
testOptions {
unitTests.returnDefaultValues = true
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:23.1.1'
compile 'com.android.support:design:23.1.1'
testCompile 'junit:junit:4.12'
testCompile "org.mockito:mockito-core:1.9.5"
}
I also have another issue. As you can see, I also imported this:
import android.support.test.runner.AndroidJUnit4;
But, even before running, it says of "runner" that "cannot resolve the symbol". I've added the TestInstrumentationRunner on build.gradle, but still not working.
OK, I solve it so, this is the solution that worked for me.
I didn't have this dependences, so I add them to the build.gradle script:
androidTestCompile 'com.android.support:support-annotations:23.1.1'
androidTestCompile 'com.android.support.test:runner:0.4.1'
androidTestCompile 'com.android.support.test:rules:0.4.1'
I am trying to add some unit tests to my app. I am developing my app in Android Studio
This is what I did.
Added a new package
Created a class in new package which extends TestCase
Added following method to created class
#SmallTest
public void basicTest() {
assertEquals("abc", "abc");
}
Added following to defaultConfig section in build.gradle
testApplicationId "newly.added.package.name"
testInstrumentationRunner "android.test.InstrumentationTestRunner"
Executed following command in Android Studio Terminal
gradlew.bat connectedAndroidTest
But, when I checked the generated html report, it shows that 0 tests were run.
I tried following, but none of them made a difference to the output of gradlew.bat connectedAndroidTest command.
Added an incorrect package name to testApplicationId in build.gradle.
Disconnected device
Why doesn't my test case get executed? What have I missed?
Following is my build.gradle
apply plugin: 'com.android.application'
android {
compileSdkVersion 20
buildToolsVersion "21.1.1"
defaultConfig {
applicationId "my.package.name"
minSdkVersion 12
targetSdkVersion 18
testApplicationId "my.package.name.tests"
testInstrumentationRunner "android.test.InstrumentationTestRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
lintOptions {
abortOnError false
}
}
dependencies {
compile project(':my_sub_module1')
compile project(':my_sub_module2')
compile 'com.android.support:support-v4:21.0.2'
compile files('libs/my_dependent_lib-1-7-4.jar')
compile 'com.google.code.gson:gson:2.3'
}
repositories {
mavenCentral()
}
You should use the following testInstrumentationRunner:
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
Also, click Build Variants on the left side of Android Studio, and select
Android Instrumentation Tests
in the dropdown.