Skip to content

Commit ec37eef

Browse files
committed
Ensure unique test-report directory per variant, even for custom paths
As per the Java-based JUnit 5 plugin, a project's test results were always saved in the same directory ("build/test-results/junit-platform"). On Android, this poses a problem because of its inherent multi-variant nature, so during the execution, the TestEngine's results would overwrite the contents at all times, rendering it impossible to obtain per-variant reports. This also in turn breaks incrementalism of our JUnit 5 tasks, since the output is never quite the same for most tasks. This commit includes the task variant's name into the output path. It also takes into account users providing a custom path using the Extension's `reportsDir` property by appending the variant-specific suffix at the end. Some unit tests have been installed to verify this new behavior as well. Fixes #36
1 parent 7d8a669 commit ec37eef

File tree

5 files changed

+92
-34
lines changed

5 files changed

+92
-34
lines changed

android-junit5-tests/testAgp2x/src/test/groovy/de/mannodermaus/gradle/plugins/junit5/AGP2PluginSpec.groovy

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package de.mannodermaus.gradle.plugins.junit5
22

3+
import de.mannodermaus.gradle.plugins.junit5.tasks.AndroidJUnit5JacocoReport
4+
import de.mannodermaus.gradle.plugins.junit5.tasks.AndroidJUnit5UnitTest
5+
import de.mannodermaus.gradle.plugins.junit5.util.TaskUtils
36
import org.gradle.api.Project
47

58
/*
@@ -28,17 +31,21 @@ class AGP2PluginSpec extends BasePluginSpec {
2831
then:
2932
// These statements automatically assert the existence of the tasks,
3033
// and raise an Exception if absent
31-
def runDebugFree = project.tasks.getByName("junitPlatformTestFreeDebug")
32-
def runDebugPaid = project.tasks.getByName("junitPlatformTestPaidDebug")
33-
def runReleaseFree = project.tasks.getByName("junitPlatformTestFreeRelease")
34-
def runReleasePaid = project.tasks.getByName("junitPlatformTestPaidRelease")
35-
def runAll = project.tasks.getByName("junitPlatformTest")
34+
def expectedVariants = ["freeDebug", "paidDebug", "freeRelease", "paidRelease"]
3635

3736
// Assert that dependency chain is valid
38-
assert runAll.getDependsOn().contains(runDebugFree)
39-
assert runAll.getDependsOn().contains(runDebugPaid)
40-
assert runAll.getDependsOn().contains(runReleaseFree)
41-
assert runAll.getDependsOn().contains(runReleasePaid)
37+
def expectedVariantTasks = expectedVariants
38+
.collect { project.tasks.getByName("junitPlatformTest${it.capitalize()}") }
39+
.collect { it as AndroidJUnit5UnitTest }
40+
def runAllTask = project.tasks.getByName("junitPlatformTest")
41+
expectedVariantTasks.each { assert runAllTask.getDependsOn().contains(it) }
42+
43+
// Assert that report directories are correctly to individual folders
44+
def uniqueReportDirs = expectedVariantTasks
45+
.collect { TaskUtils.argument(it, "--reports-dir") }
46+
.unique()
47+
48+
assert expectedVariantTasks.size() == uniqueReportDirs.size()
4249
}
4350

4451
def "Application: Jacoco Integration with Product Flavors"() {
@@ -61,16 +68,13 @@ class AGP2PluginSpec extends BasePluginSpec {
6168
then:
6269
// These statements automatically assert the existence of the tasks,
6370
// and raise an Exception if absent
64-
def runDebugFree = project.tasks.getByName("jacocoTestReportFreeDebug")
65-
def runDebugPaid = project.tasks.getByName("jacocoTestReportPaidDebug")
66-
def runReleaseFree = project.tasks.getByName("jacocoTestReportFreeRelease")
67-
def runReleasePaid = project.tasks.getByName("jacocoTestReportPaidRelease")
68-
def runAll = project.tasks.getByName("jacocoTestReport")
71+
def expectedVariants = ["freeDebug", "paidDebug", "freeRelease", "paidRelease"]
6972

7073
// Assert that dependency chain is valid
71-
assert runAll.getDependsOn().contains(runDebugFree)
72-
assert runAll.getDependsOn().contains(runDebugPaid)
73-
assert runAll.getDependsOn().contains(runReleaseFree)
74-
assert runAll.getDependsOn().contains(runReleasePaid)
74+
def expectedVariantTasks = expectedVariants
75+
.collect { project.tasks.getByName("jacocoTestReport${it.capitalize()}") }
76+
.collect { it as AndroidJUnit5JacocoReport }
77+
def runAllTask = project.tasks.getByName("jacocoTestReport")
78+
expectedVariantTasks.each { assert runAllTask.getDependsOn().contains(it) }
7579
}
7680
}

android-junit5-tests/testAgp3x/src/test/groovy/de/mannodermaus/gradle/plugins/junit5/AGP3PluginSpec.groovy

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package de.mannodermaus.gradle.plugins.junit5
22

3+
import de.mannodermaus.gradle.plugins.junit5.tasks.AndroidJUnit5JacocoReport
4+
import de.mannodermaus.gradle.plugins.junit5.tasks.AndroidJUnit5UnitTest
5+
import de.mannodermaus.gradle.plugins.junit5.util.TaskUtils
36
import org.gradle.api.Project
47

58
/*
@@ -31,15 +34,21 @@ class AGP3PluginSpec extends BasePluginSpec {
3134
then:
3235
// These statements automatically assert the existence of the tasks,
3336
// and raise an Exception if absent
34-
def runDebugFree = project.tasks.getByName("junitPlatformTestFreeDebug")
35-
def runDebugPaid = project.tasks.getByName("junitPlatformTestPaidDebug")
36-
def runReleaseFree = project.tasks.getByName("junitPlatformTestFreeRelease")
37-
def runReleasePaid = project.tasks.getByName("junitPlatformTestPaidRelease")
38-
def runAll = project.tasks.getByName("junitPlatformTest")
37+
def expectedVariants = ["freeDebug", "paidDebug", "freeRelease", "paidRelease"]
3938

4039
// Assert that dependency chain is valid
41-
assert runAll.getDependsOn()
42-
.containsAll([runDebugFree, runDebugPaid, runReleaseFree, runReleasePaid])
40+
def expectedVariantTasks = expectedVariants
41+
.collect { project.tasks.getByName("junitPlatformTest${it.capitalize()}") }
42+
.collect { it as AndroidJUnit5UnitTest }
43+
def runAllTask = project.tasks.getByName("junitPlatformTest")
44+
expectedVariantTasks.each { assert runAllTask.getDependsOn().contains(it) }
45+
46+
// Assert that report directories are correctly to individual folders
47+
def uniqueReportDirs = expectedVariantTasks
48+
.collect { TaskUtils.argument(it, "--reports-dir") }
49+
.unique()
50+
51+
assert expectedVariantTasks.size() == uniqueReportDirs.size()
4352
}
4453

4554
def "Application: Jacoco Integration with Product Flavors"() {
@@ -65,15 +74,14 @@ class AGP3PluginSpec extends BasePluginSpec {
6574
then:
6675
// These statements automatically assert the existence of the tasks,
6776
// and raise an Exception if absent
68-
def runDebugFree = project.tasks.getByName("jacocoTestReportFreeDebug")
69-
def runDebugPaid = project.tasks.getByName("jacocoTestReportPaidDebug")
70-
def runReleaseFree = project.tasks.getByName("jacocoTestReportFreeRelease")
71-
def runReleasePaid = project.tasks.getByName("jacocoTestReportPaidRelease")
72-
def runAll = project.tasks.getByName("jacocoTestReport")
77+
def expectedVariants = ["freeDebug", "paidDebug", "freeRelease", "paidRelease"]
7378

7479
// Assert that dependency chain is valid
75-
assert runAll.getDependsOn()
76-
.containsAll([runDebugFree, runDebugPaid, runReleaseFree, runReleasePaid])
80+
def expectedVariantTasks = expectedVariants
81+
.collect { project.tasks.getByName("jacocoTestReport${it.capitalize()}") }
82+
.collect { it as AndroidJUnit5JacocoReport }
83+
def runAllTask = project.tasks.getByName("jacocoTestReport")
84+
expectedVariantTasks.each { assert runAllTask.getDependsOn().contains(it) }
7785
}
7886

7987
def "Feature: Basic Integration"() {

android-junit5-tests/testCommon/src/test/groovy/de/mannodermaus/gradle/plugins/junit5/BasePluginSpec.groovy

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package de.mannodermaus.gradle.plugins.junit5
22

33
import de.mannodermaus.gradle.plugins.junit5.tasks.AndroidJUnit5JacocoReport
44
import de.mannodermaus.gradle.plugins.junit5.tasks.AndroidJUnit5UnitTest
5+
import de.mannodermaus.gradle.plugins.junit5.util.TaskUtils
56
import de.mannodermaus.gradle.plugins.junit5.util.TestEnvironment
67
import de.mannodermaus.gradle.plugins.junit5.util.TestProjectFactory
78
import org.apache.commons.io.FileUtils
@@ -252,6 +253,30 @@ abstract class BasePluginSpec extends Specification {
252253
assert !runRelease.environment.containsKey("MY_ENV_VAR")
253254
}
254255

256+
def "Custom reportsDir still creates unique path per variant"() {
257+
when:
258+
Project project = factory.newProject(rootProject())
259+
.asAndroidApplication()
260+
.applyJunit5Plugin()
261+
.build()
262+
263+
project.junitPlatform {
264+
reportsDir project.file("${project.buildDir.absolutePath}/other-path/test-reports")
265+
}
266+
267+
project.evaluate()
268+
269+
then:
270+
def expectedVariants = ["debug", "release"]
271+
def expectedReportDirs = expectedVariants
272+
.collect { project.tasks.getByName("junitPlatformTest${it.capitalize()}") }
273+
.collect { it as AndroidJUnit5UnitTest }
274+
.collect { TaskUtils.argument(it, "--reports-dir") }
275+
.unique()
276+
277+
assert expectedReportDirs.size() == expectedVariants.size()
278+
}
279+
255280
def "Application: Basic Integration"() {
256281
when:
257282
Project project = factory.newProject(rootProject())
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package de.mannodermaus.gradle.plugins.junit5.util
2+
3+
import org.gradle.api.tasks.JavaExec
4+
5+
import javax.annotation.Nullable
6+
7+
class TaskUtils {
8+
private TaskUtils() {}
9+
10+
@Nullable
11+
static String argument(JavaExec task, String argumentName) {
12+
def index = task.args.indexOf(argumentName)
13+
return index == -1 || task.args.size() == index + 1 ? null : task.args[index + 1]
14+
}
15+
}

android-junit5/src/main/kotlin/de/mannodermaus/gradle/plugins/junit5/tasks/UnitTest.kt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,8 +189,14 @@ open class AndroidJUnit5UnitTest : JavaExec() {
189189
private fun configureTaskOutputs(
190190
task: AndroidJUnit5UnitTest,
191191
junit5: AndroidJUnitPlatformExtension): File {
192-
val reportsDir = junit5.reportsDir ?:
193-
project.file("${project.buildDir}/test-results/junit-platform")
192+
val reportsDir = if (junit5.reportsDir != null) {
193+
// Ensure per-variant directory even with a custom "reportsDir"
194+
project.file("${junit5.reportsDir.absolutePath}/${variant.name}")
195+
} else {
196+
// Default path
197+
project.file("${project.buildDir}/test-results/${variant.name}/junit-platform")
198+
}
199+
194200
task.outputs.dir(reportsDir)
195201
return reportsDir
196202
}

0 commit comments

Comments
 (0)