Skip to content

Commit 098257f

Browse files
authored
Use legacy test name formatting for Test Orchestrator, too (#342)
This removes the need to use the deprecated @UseTechnicalNames annotation, so let's get rid of that anyway. The tool now controls the legacy mode! Finally, prevent people from using parallel test execution with the Orchestrator.
1 parent a71c2d0 commit 098257f

File tree

7 files changed

+29
-22
lines changed

7 files changed

+29
-22
lines changed

instrumentation/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Change Log
88
- Fix invalid naming of dynamic tests when executing only a singular test method from the IDE (#317, #339)
99
- Prevent test methods incorrectly defined as Kotlin top-level functions from messing up Android's internal test counting, causing issues like "Expected N+1 tests, received N" (#316)
1010
- Prevent test classes ignored by a tag from being considered for test execution, causing issues like "Expected N+1 tests, received N" (#298)
11+
- Improve integration with Android Test Orchestrator and remove the need for `@UseTechnicalNames` (#337)
1112

1213
## 1.4.0 (2023-11-05)
1314

instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/extensions/TestIdentifierExt.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ internal val TestIdentifier.isDynamicTest: Boolean
3434
/**
3535
* Returns a formatted version of this identifier's name,
3636
* which is compatible with the quirks and limitations
37-
* of the Android Instrumentation, esp. when the [isIsolatedMethodRun]
37+
* of the Android Instrumentation, esp. when the [legacyFormat]
3838
* flag is enabled.
3939
*/
40-
internal fun TestIdentifier.format(isIsolatedMethodRun: Boolean = false): String =
41-
TestNameFormatter.format(this, isIsolatedMethodRun)
40+
internal fun TestIdentifier.format(legacyFormat: Boolean = false): String =
41+
TestNameFormatter.format(this, legacyFormat)

instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/formatters/TestNameFormatter.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import org.junit.platform.launcher.TestIdentifier
88
* Android instrumentation (e.g. on isolated test runs).
99
*/
1010
internal object TestNameFormatter {
11-
fun format(identifier: TestIdentifier, isIsolatedMethodRun: Boolean = false): String {
12-
// During isolated executions of a single test method,
11+
fun format(identifier: TestIdentifier, legacyFormat: Boolean = false): String {
12+
// When requesting the legacy format of the formatter,
1313
// construct a technical version of its name for backwards compatibility
1414
// with the JUnit 4-based instrumentation of Android by stripping the brackets of parameterized tests completely.
1515
// If this didn't happen, running them from the IDE will cause "No tests found" errors.
@@ -19,7 +19,7 @@ internal object TestNameFormatter {
1919
// - #199 & #207 (the original unearthing of this behavior)
2020
// - #317 (making an exception for dynamic tests)
2121
// - #339 (retain indices of parameterized methods to avoid premature filtering by JUnit 4's test discovery)
22-
if (isIsolatedMethodRun) {
22+
if (legacyFormat) {
2323
val reportName = identifier.legacyReportingName
2424
val paramStartIndex = reportName.indexOf('(')
2525
if (paramStartIndex > -1) {

instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/runners/AndroidJUnit5.kt

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
package de.mannodermaus.junit5.internal.runners
22

33
import android.annotation.SuppressLint
4-
import android.util.Log
54
import androidx.annotation.VisibleForTesting
6-
import de.mannodermaus.junit5.internal.LOG_TAG
7-
import de.mannodermaus.junit5.internal.LibcoreAccess
85
import de.mannodermaus.junit5.internal.runners.notification.ParallelRunNotifier
96
import org.junit.platform.engine.discovery.MethodSelector
107
import org.junit.platform.launcher.core.LauncherFactory
@@ -44,12 +41,25 @@ internal class AndroidJUnit5(
4441
private fun generateTestTree(params: AndroidJUnit5RunnerParams): AndroidJUnitPlatformTestTree {
4542
val selectors = params.createSelectors(testClass)
4643
val isIsolatedMethodRun = selectors.size == 1 && selectors.first() is MethodSelector
44+
val isUsingOrchestrator = params.isUsingOrchestrator
4745
val request = params.createDiscoveryRequest(selectors)
4846

47+
// Validate if run can be executed
48+
if (isUsingOrchestrator && params.isParallelExecutionEnabled) {
49+
throw RuntimeException(
50+
"""
51+
Running tests with the Android Test Orchestrator does not work with parallel tests,
52+
since some information must be retained across parallel test execution,
53+
and the isolated nature of the Android Test Orchestrator thwarts these efforts.
54+
Please disable either setting and try again.
55+
""".trimIndent(),
56+
)
57+
}
58+
4959
return AndroidJUnitPlatformTestTree(
5060
testPlan = launcher.discover(request),
5161
testClass = testClass,
52-
isIsolatedMethodRun = isIsolatedMethodRun,
62+
needLegacyFormat = isIsolatedMethodRun || isUsingOrchestrator,
5363
isParallelExecutionEnabled = params.isParallelExecutionEnabled,
5464
)
5565
}

instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/runners/AndroidJUnit5RunnerParams.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ internal data class AndroidJUnit5RunnerParams(
3333
val isParallelExecutionEnabled: Boolean
3434
get() = configurationParameters["junit.jupiter.execution.parallel.enabled"] == "true"
3535

36+
val isUsingOrchestrator: Boolean
37+
get() = arguments.getString("orchestratorService") != null
38+
3639
internal companion object {
3740
fun create(): AndroidJUnit5RunnerParams {
3841
val instrumentation = InstrumentationRegistry.getInstrumentation()

instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/runners/AndroidJUnitPlatformTestTree.kt

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import org.junit.platform.engine.support.descriptor.MethodSource
1212
import org.junit.platform.launcher.TestIdentifier
1313
import org.junit.platform.launcher.TestPlan
1414
import org.junit.platform.suite.api.SuiteDisplayName
15-
import org.junit.platform.suite.api.UseTechnicalNames
1615
import org.junit.runner.Description
1716
import java.util.Optional
1817
import java.util.function.Predicate
@@ -26,7 +25,7 @@ import java.util.function.Predicate
2625
internal class AndroidJUnitPlatformTestTree(
2726
testPlan: TestPlan,
2827
testClass: Class<*>,
29-
private val isIsolatedMethodRun: Boolean,
28+
private val needLegacyFormat: Boolean,
3029
val isParallelExecutionEnabled: Boolean,
3130
) {
3231

@@ -39,7 +38,7 @@ internal class AndroidJUnitPlatformTestTree(
3938
// Order matters here, since all dynamic tests are also containers,
4039
// but not all containers are dynamic tests
4140
fun getTestName(identifier: TestIdentifier): String = when {
42-
identifier.isDynamicTest -> if (isIsolatedMethodRun) {
41+
identifier.isDynamicTest -> if (needLegacyFormat) {
4342
// In isolated method runs, there is no need to compose
4443
// dynamic test names from multiple pieces, as the
4544
// Android Instrumentation only looks at the raw method name
@@ -69,7 +68,7 @@ internal class AndroidJUnitPlatformTestTree(
6968

7069
identifier.isContainer -> getTechnicalName(identifier)
7170

72-
else -> identifier.format(isIsolatedMethodRun)
71+
else -> identifier.format(needLegacyFormat)
7372
}
7473

7574
// Do not expose our custom TestPlan, because JUnit Platform wouldn't like that very much.
@@ -82,13 +81,7 @@ internal class AndroidJUnitPlatformTestTree(
8281
}
8382

8483
private fun generateSuiteDescription(testPlan: TestPlan, testClass: Class<*>): Description {
85-
val displayName = if (testClass.isAnnotationPresent(UseTechnicalNames::class.java)) {
86-
testClass.name
87-
} else {
88-
getSuiteDisplayName(testClass)
89-
}
90-
91-
return Description.createSuiteDescription(displayName).also {
84+
return Description.createSuiteDescription(getSuiteDisplayName(testClass)).also {
9285
buildDescriptionTree(it, testPlan)
9386
}
9487
}

instrumentation/runner/src/test/kotlin/de/mannodermaus/junit5/internal/runners/AndroidJUnitPlatformTestTreeTests.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ class AndroidJUnitPlatformTestTreeTests {
116116
val tree = AndroidJUnitPlatformTestTree(
117117
testPlan = plan,
118118
testClass = cls.java,
119-
isIsolatedMethodRun = isIsolatedMethodRun,
119+
needLegacyFormat = isIsolatedMethodRun,
120120
isParallelExecutionEnabled = false,
121121
)
122122

0 commit comments

Comments
 (0)