Skip to content

Commit a0f222e

Browse files
authored
Fix unit tested code not reported as covered (#19)
- Fix a few issues with unit test coverage. Code in module A that is touched by unit tests in module B is now correctly reported as covered (fixes #18). - Add extra test cases to cover more cases in the Kotlin/Java code and Library/App module matrix. - Remove some unnessecary files from the integration test.
1 parent e9cee62 commit a0f222e

File tree

37 files changed

+338
-358
lines changed

37 files changed

+338
-358
lines changed

plugin/src/main/kotlin/org/neotech/plugin/rootcoverage/RootCoveragePlugin.kt

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ import org.gradle.api.DomainObjectSet
88
import org.gradle.api.GradleException
99
import org.gradle.api.Plugin
1010
import org.gradle.api.Project
11+
import org.gradle.api.file.FileTree
12+
import org.gradle.api.tasks.testing.Test
1113
import org.gradle.testing.jacoco.plugins.JacocoPlugin
14+
import org.gradle.testing.jacoco.plugins.JacocoTaskExtension
1215

1316
@Suppress("unused")
1417
class RootCoveragePlugin : Plugin<Project> {
@@ -60,19 +63,30 @@ class RootCoveragePlugin : Plugin<Project> {
6063
private fun getBuildVariantFor(project: Project): String =
6164
rootProjectExtension.buildVariantOverrides[project.path] ?: rootProjectExtension.buildVariant
6265

63-
private fun getExecutionDataFilePatterns(): List<String> {
64-
val list = mutableListOf<String>()
66+
private fun getExecutionDataFileTree(project: Project): FileTree {
67+
val rootFolderPatterns = mutableListOf<String>()
68+
val buildFolderPatterns = mutableListOf<String>()
6569
if (rootProjectExtension.includeUnitTestResults()) {
66-
list.add("jacoco/test*UnitTest.exec")
70+
buildFolderPatterns.add("jacoco/test*UnitTest.exec")
71+
72+
// TODO instead of hardcoding this, obtain the location from the test tasks, something like this:
73+
// tasks.withType(Test::class.java).all { testTask ->
74+
// testTask.extensions.findByType(JacocoTaskExtension::class.java)?.apply {
75+
// destinationFile
76+
// }
77+
// }
78+
rootFolderPatterns.add("jacoco.exec")
6779
}
6880
if (rootProjectExtension.includeAndroidTestResults()) {
6981
// Android Build Tools Plugin 3.2
70-
list.add("outputs/code-coverage/connected/*coverage.ec")
82+
buildFolderPatterns.add("outputs/code-coverage/connected/*coverage.ec")
7183

7284
// Android Build Tools Plugin 3.3+
73-
list.add("outputs/code_coverage/*/connected/*coverage.ec")
85+
buildFolderPatterns.add("outputs/code_coverage/*/connected/*coverage.ec")
7486
}
75-
return list
87+
88+
return project.fileTree(project.buildDir, includes = buildFolderPatterns) +
89+
project.fileTree(project.projectDir, includes = rootFolderPatterns)
7690
}
7791

7892
/**
@@ -142,7 +156,6 @@ class RootCoveragePlugin : Plugin<Project> {
142156
when (extension) {
143157
is LibraryExtension -> {
144158
extension.libraryVariants.all { variant ->
145-
146159
if (variant.buildType.isTestCoverageEnabled && variant.name.capitalize() == buildVariant.capitalize()) {
147160
if (subProject.plugins.withType(JacocoPlugin::class.java).isEmpty()) {
148161
subProject.logger.warn("Warning: Jacoco plugin was not found for project: '${subProject.name}', it has been applied automatically but you should do this manually. Build file: ${subProject.buildFile}")
@@ -201,9 +214,8 @@ class RootCoveragePlugin : Plugin<Project> {
201214

202215
task.sourceDirectories = project.files(sourceFiles)
203216
task.classDirectories = project.files(javaClassTrees, kotlinClassTree)
204-
task.executionData = project.fileTree(project.buildDir, includes = getExecutionDataFilePatterns())
217+
task.executionData = getExecutionDataFileTree(project)
205218
}
206-
207219
return codeCoverageReportTask.get()
208220
}
209221

plugin/src/test/kotlin/org/neotech/plugin/rootcoverage/IntegrationTest.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ class IntegrationTest(
4242

4343
report.assertFullCoverage("org.neotech.library.android", "LibraryAndroidJava")
4444
report.assertFullCoverage("org.neotech.library.android", "LibraryAndroidKotlin")
45+
report.assertFullCoverage("org.neotech.app", "AppJava")
46+
report.assertFullCoverage("org.neotech.app", "AppKotlin")
4547
}
4648

4749
companion object {
@@ -54,7 +56,6 @@ class IntegrationTest(
5456
val testFixtures = File("src/test/test-fixtures").listFiles()?.filter { it.isDirectory }
5557
?: error("Could not list test fixture directories")
5658
val gradleVersions = arrayOf("5.4.1", "5.5.1", "5.6.4")
57-
5859
return testFixtures.flatMap { file ->
5960
gradleVersions.map { gradleVersion ->
6061
arrayOf("${file.name}-$gradleVersion", file, gradleVersion)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package org.neotech.app.multimoduleapplication;
2+
3+
import androidx.test.ext.junit.runners.AndroidJUnit4;
4+
5+
import org.junit.Test;
6+
import org.junit.runner.RunWith;
7+
import org.neotech.app.AppJava;
8+
import org.neotech.app.AppKotlin;
9+
import org.neotech.library.android.LibraryAndroidJava;
10+
import org.neotech.library.android.LibraryAndroidKotlin;
11+
12+
@RunWith(AndroidJUnit4.class)
13+
public class AppJavaInstrumentedTest {
14+
15+
@Test
16+
public void touchJavaCodeInApp() {
17+
AppJava.getInstance().touchedByJavaInstrumentedTestInApp();
18+
}
19+
20+
@Test
21+
public void touchKotlinCodeInApp() {
22+
AppKotlin.touchedByJavaInstrumentedTestInApp();
23+
}
24+
25+
@Test
26+
public void touchJavaCodeInLibrary() {
27+
LibraryAndroidJava.getInstance().touchedByJavaInstrumentedTestInApp();
28+
}
29+
30+
@Test
31+
public void touchKotlinCodeInLibrary() {
32+
LibraryAndroidKotlin.touchedByJavaInstrumentedTestInApp();
33+
}
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package org.neotech.app.multimoduleapplication
2+
3+
import androidx.test.ext.junit.runners.AndroidJUnit4
4+
import org.junit.Test
5+
import org.junit.runner.RunWith
6+
import org.neotech.app.AppJava
7+
import org.neotech.app.AppKotlin
8+
import org.neotech.library.android.LibraryAndroidJava
9+
import org.neotech.library.android.LibraryAndroidKotlin
10+
11+
@RunWith(AndroidJUnit4::class)
12+
class AppKotlinInstrumentedTest {
13+
14+
@Test
15+
fun touchJavaCodeInApp() {
16+
AppJava.getInstance().touchedByKotlinInstrumentedTestInApp()
17+
}
18+
19+
@Test
20+
fun touchKotlinCodeInApp() {
21+
AppKotlin.touchedByKotlinInstrumentedTestInApp()
22+
}
23+
24+
@Test
25+
fun touchJavaCodeInLibrary() {
26+
LibraryAndroidJava.getInstance().touchedByKotlinInstrumentedTestInApp()
27+
}
28+
29+
@Test
30+
fun touchKotlinCodeInLibrary() {
31+
LibraryAndroidKotlin.touchedByKotlinInstrumentedTestInApp()
32+
}
33+
}

plugin/src/test/test-fixtures/multi-module/app/src/androidTest/java/org/neotech/app/multimoduleapplication/TouchLibraryCodeFromJavaAndroidTest.java

Lines changed: 0 additions & 22 deletions
This file was deleted.
Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,2 @@
11
<?xml version="1.0" encoding="utf-8"?>
2-
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3-
package="org.neotech.app">
4-
5-
<application
6-
android:allowBackup="true"
7-
android:icon="@mipmap/ic_launcher"
8-
android:label="@string/app_name"
9-
android:roundIcon="@mipmap/ic_launcher_round"
10-
android:supportsRtl="true"
11-
android:theme="@style/AppTheme">
12-
<activity android:name=".MainActivity">
13-
<intent-filter>
14-
<action android:name="android.intent.action.MAIN" />
15-
16-
<category android:name="android.intent.category.LAUNCHER" />
17-
</intent-filter>
18-
</activity>
19-
</application>
20-
21-
</manifest>
2+
<manifest package="org.neotech.app" />
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package org.neotech.app;
2+
3+
public final class AppJava {
4+
5+
private static AppJava INSTANCE;
6+
7+
public static synchronized AppJava getInstance() {
8+
if (INSTANCE == null) {
9+
INSTANCE = new AppJava();
10+
}
11+
return INSTANCE;
12+
}
13+
14+
private AppJava() {
15+
16+
}
17+
18+
public String touchedByJavaInstrumentedTestInApp() {
19+
return "touchedByJavaInstrumentedTestInApp";
20+
}
21+
22+
public String touchedByJavaUnitTestInApp() {
23+
return "touchedByJavaUnitTestInApp";
24+
}
25+
26+
public String touchedByKotlinInstrumentedTestInApp() {
27+
return "touchedByKotlinInstrumentedTestInApp";
28+
}
29+
30+
public String touchedByKotlinUnitTestInApp() {
31+
return "touchedByKotlinUnitTestInApp";
32+
}
33+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package org.neotech.app
2+
3+
object AppKotlin {
4+
5+
@JvmStatic
6+
fun touchedByJavaInstrumentedTestInApp(): String {
7+
return "touchedByJavaInstrumentedTestInApp"
8+
}
9+
10+
@JvmStatic
11+
fun touchedByJavaUnitTestInApp(): String {
12+
return "touchedByJavaUnitTestInApp"
13+
}
14+
15+
fun touchedByKotlinInstrumentedTestInApp(): String {
16+
return "touchedByKotlinInstrumentedTestInApp"
17+
}
18+
19+
fun touchedByKotlinUnitTestInApp(): String {
20+
return "touchedByKotlinUnitTestInApp"
21+
}
22+
}

plugin/src/test/test-fixtures/multi-module/app/src/main/java/org/neotech/app/MainActivity.kt

Lines changed: 0 additions & 15 deletions
This file was deleted.

plugin/src/test/test-fixtures/multi-module/app/src/main/res/drawable-v24/ic_launcher_foreground.xml

Lines changed: 0 additions & 34 deletions
This file was deleted.

0 commit comments

Comments
 (0)