From 63066e11bf16e2be2f5c93e924913427058be5c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20Varga?= Date: Mon, 18 Mar 2024 11:39:55 +0100 Subject: [PATCH 1/2] test: Add test for repeated, test template and nested tests --- .../BlockJUnit4ClassRunnerExtensions.kt | 42 +++++++++++---- .../internal/JUnit5RobolectricTestRunner.kt | 8 +++ .../RobolectricExtensionNestedSelfTest.kt | 24 +++++++++ .../RobolectricExtensionRepeatedSelfTest.kt | 40 ++++++++++++++ ...obolectricExtensionTestTemplateSelfTest.kt | 52 +++++++++++++++++++ 5 files changed, 155 insertions(+), 11 deletions(-) create mode 100644 robolectric-extension/src/test/kotlin/tech/apter/junit/jupiter/robolectric/RobolectricExtensionNestedSelfTest.kt create mode 100644 robolectric-extension/src/test/kotlin/tech/apter/junit/jupiter/robolectric/RobolectricExtensionRepeatedSelfTest.kt create mode 100644 robolectric-extension/src/test/kotlin/tech/apter/junit/jupiter/robolectric/RobolectricExtensionTestTemplateSelfTest.kt diff --git a/robolectric-extension/src/main/kotlin/tech/apter/junit/jupiter/robolectric/internal/BlockJUnit4ClassRunnerExtensions.kt b/robolectric-extension/src/main/kotlin/tech/apter/junit/jupiter/robolectric/internal/BlockJUnit4ClassRunnerExtensions.kt index 3f1d764..d057213 100644 --- a/robolectric-extension/src/main/kotlin/tech/apter/junit/jupiter/robolectric/internal/BlockJUnit4ClassRunnerExtensions.kt +++ b/robolectric-extension/src/main/kotlin/tech/apter/junit/jupiter/robolectric/internal/BlockJUnit4ClassRunnerExtensions.kt @@ -8,10 +8,14 @@ import org.junit.jupiter.api.AfterAll import org.junit.jupiter.api.BeforeAll import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Disabled +import org.junit.jupiter.api.RepeatedTest import org.junit.jupiter.api.Test import org.junit.jupiter.api.TestFactory +import org.junit.jupiter.api.TestTemplate import org.junit.runners.BlockJUnit4ClassRunner import org.junit.runners.model.FrameworkMethod +import org.junit.runners.model.TestClass +import java.lang.reflect.Modifier import java.util.Collections private val parameterizedTestAnnotation: Class? by lazy { @@ -24,19 +28,35 @@ private val parameterizedTestAnnotation: Class? by lazy { } internal fun BlockJUnit4ClassRunner.computeJUnit5TestMethods(): MutableList { - val testMethods = testClass.getAnnotatedMethods(Test::class.java) - val testFactoryMethods = testClass.getAnnotatedMethods(TestFactory::class.java) - val parameterizedTestMethods = if (parameterizedTestAnnotation == null) { - emptyList() - } else { - testClass.getAnnotatedMethods(parameterizedTestAnnotation) + fun testMethods(testClass: TestClass): MutableList { + val testMethods = testClass.getAnnotatedMethods(Test::class.java) + val testFactoryMethods = testClass.getAnnotatedMethods(TestFactory::class.java) + val repeatedTestMethods = testClass.getAnnotatedMethods(RepeatedTest::class.java) + val testTemplateMethods = testClass.getAnnotatedMethods(TestTemplate::class.java) + val parameterizedTestMethods = if (parameterizedTestAnnotation == null) { + emptyList() + } else { + testClass.getAnnotatedMethods(parameterizedTestAnnotation) + } + + val nestedTestMethods = testClass + .javaClass + .declaredClasses + .filter { !Modifier.isStatic(it.modifiers) } + .map { testMethods(TestClass(it)) } + .flatten() + + val methods = mutableListOf() + methods.addAll(testMethods) + methods.addAll(testTemplateMethods) + methods.addAll(testFactoryMethods) + methods.addAll(repeatedTestMethods) + methods.addAll(parameterizedTestMethods) + methods.addAll(nestedTestMethods) + return Collections.unmodifiableList(methods) } - val methods = mutableListOf() - methods.addAll(testMethods) - methods.addAll(testFactoryMethods) - methods.addAll(parameterizedTestMethods) - return Collections.unmodifiableList(methods) + return testMethods(testClass) } @Suppress("UnusedReceiverParameter") diff --git a/robolectric-extension/src/main/kotlin/tech/apter/junit/jupiter/robolectric/internal/JUnit5RobolectricTestRunner.kt b/robolectric-extension/src/main/kotlin/tech/apter/junit/jupiter/robolectric/internal/JUnit5RobolectricTestRunner.kt index aea02fb..85206a6 100644 --- a/robolectric-extension/src/main/kotlin/tech/apter/junit/jupiter/robolectric/internal/JUnit5RobolectricTestRunner.kt +++ b/robolectric-extension/src/main/kotlin/tech/apter/junit/jupiter/robolectric/internal/JUnit5RobolectricTestRunner.kt @@ -53,6 +53,10 @@ internal class JUnit5RobolectricTestRunner(clazz: Class<*>, injector: Injector = override fun computeTestMethods() = computeJUnit5TestMethods() + override fun validateNoNonStaticInnerClass(errors: MutableList) { + // Skip validation + } + override fun isIgnored(child: FrameworkMethod) = isJUnit5Ignored(child) override fun validatePublicVoidNoArgMethods( @@ -68,6 +72,10 @@ internal class JUnit5RobolectricTestRunner(clazz: Class<*>, injector: Injector = RobolectricTestRunner.HelperTestRunner(bootstrappedTestClass) { override fun computeTestMethods(): MutableList = computeJUnit5TestMethods() + override fun validateNoNonStaticInnerClass(errors: MutableList) { + // Skip validation + } + override fun isIgnored(child: FrameworkMethod) = isJUnit5Ignored(child) override fun validatePublicVoidNoArgMethods( diff --git a/robolectric-extension/src/test/kotlin/tech/apter/junit/jupiter/robolectric/RobolectricExtensionNestedSelfTest.kt b/robolectric-extension/src/test/kotlin/tech/apter/junit/jupiter/robolectric/RobolectricExtensionNestedSelfTest.kt new file mode 100644 index 0000000..58d878f --- /dev/null +++ b/robolectric-extension/src/test/kotlin/tech/apter/junit/jupiter/robolectric/RobolectricExtensionNestedSelfTest.kt @@ -0,0 +1,24 @@ +package tech.apter.junit.jupiter.robolectric + +import android.app.Application +import android.content.Context +import androidx.test.core.app.ApplicationProvider +import org.junit.jupiter.api.Nested +import org.junit.jupiter.api.assertDoesNotThrow +import org.junit.jupiter.api.extension.ExtendWith +import kotlin.test.Test +import kotlin.test.assertIs +import kotlin.test.assertNotNull + +@ExtendWith(RobolectricExtension::class) +class RobolectricExtensionNestedSelfTest { + @Nested + inner class NestedSelfTest { + @Test + fun `Given a test extended with robolectric when call a nested test then robolectric should be available`() { + val application = assertDoesNotThrow { ApplicationProvider.getApplicationContext() } + assertNotNull(application) + assertIs(application, "application") + } + } +} diff --git a/robolectric-extension/src/test/kotlin/tech/apter/junit/jupiter/robolectric/RobolectricExtensionRepeatedSelfTest.kt b/robolectric-extension/src/test/kotlin/tech/apter/junit/jupiter/robolectric/RobolectricExtensionRepeatedSelfTest.kt new file mode 100644 index 0000000..b3ed5f2 --- /dev/null +++ b/robolectric-extension/src/test/kotlin/tech/apter/junit/jupiter/robolectric/RobolectricExtensionRepeatedSelfTest.kt @@ -0,0 +1,40 @@ +package tech.apter.junit.jupiter.robolectric + +import android.app.Application +import android.content.Context +import androidx.test.core.app.ApplicationProvider +import org.junit.jupiter.api.AfterAll +import org.junit.jupiter.api.RepeatedTest +import org.junit.jupiter.api.RepetitionInfo +import org.junit.jupiter.api.assertDoesNotThrow +import org.junit.jupiter.api.extension.ExtendWith +import kotlin.test.assertEquals +import kotlin.test.assertIs +import kotlin.test.assertNotNull + +@ExtendWith(RobolectricExtension::class) +class RobolectricExtensionRepeatedSelfTest { + + @RepeatedTest(REPEATED_TEST_COUNT) + fun `Given a test extended with robolectric when call a repeated test then robolectric should be available`( + testInfo: RepetitionInfo, + ) { + testCallCount++ + val application = assertDoesNotThrow { ApplicationProvider.getApplicationContext() } + assertNotNull(application) + assertIs(application, "application") + assertEquals(REPEATED_TEST_COUNT, testInfo.totalRepetitions) + } + + companion object { + private const val REPEATED_TEST_COUNT = 3 + private var testCallCount: Int = 0 + + @AfterAll + @Throws(Exception::class) + @JvmStatic + fun `Repeated test should be called as much as REPEATED_TEST_COUNT`() { + assertEquals(REPEATED_TEST_COUNT, testCallCount) + } + } +} diff --git a/robolectric-extension/src/test/kotlin/tech/apter/junit/jupiter/robolectric/RobolectricExtensionTestTemplateSelfTest.kt b/robolectric-extension/src/test/kotlin/tech/apter/junit/jupiter/robolectric/RobolectricExtensionTestTemplateSelfTest.kt new file mode 100644 index 0000000..35dde48 --- /dev/null +++ b/robolectric-extension/src/test/kotlin/tech/apter/junit/jupiter/robolectric/RobolectricExtensionTestTemplateSelfTest.kt @@ -0,0 +1,52 @@ +package tech.apter.junit.jupiter.robolectric + +import android.app.Application +import android.content.Context +import androidx.test.core.app.ApplicationProvider +import org.junit.jupiter.api.AfterAll +import org.junit.jupiter.api.TestTemplate +import org.junit.jupiter.api.assertDoesNotThrow +import org.junit.jupiter.api.extension.ExtendWith +import org.junit.jupiter.api.extension.ExtensionContext +import org.junit.jupiter.api.extension.TestTemplateInvocationContext +import org.junit.jupiter.api.extension.TestTemplateInvocationContextProvider +import java.util.stream.Stream +import kotlin.test.assertEquals +import kotlin.test.assertIs +import kotlin.test.assertNotNull + + +@ExtendWith(RobolectricExtension::class) +class RobolectricExtensionTestTemplateSelfTest { + + @TestTemplate + @ExtendWith(RobolectricTestTemplateInvocationContextProvider::class) + fun `Given a test extended with robolectric when call a test template then robolectric should be available`() { + testCallCount++ + val application = assertDoesNotThrow { ApplicationProvider.getApplicationContext() } + assertNotNull(application) + assertIs(application, "application") + } + + companion object { + private var testCallCount: Int = 0 + + @AfterAll + @Throws(Exception::class) + @JvmStatic + fun `Test template should be called as much as defined RobolectricTestTemplateInvocationContextProvider`() { + assertEquals(2, testCallCount) + } + } +} + +private fun noOpTestTemplateInvocationContext(): TestTemplateInvocationContext = + object : TestTemplateInvocationContext {} + +private class RobolectricTestTemplateInvocationContextProvider : TestTemplateInvocationContextProvider { + override fun supportsTestTemplate(context: ExtensionContext): Boolean = true + + override fun provideTestTemplateInvocationContexts(context: ExtensionContext): Stream { + return Stream.of(noOpTestTemplateInvocationContext(), noOpTestTemplateInvocationContext()) + } +} From b57865564246707119b0e24ad3e34a68a7aa11c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20Varga?= Date: Tue, 19 Mar 2024 14:27:58 +0100 Subject: [PATCH 2/2] test: Add test for repeated, test template and nested tests --- .../robolectric/RobolectricExtensionTestTemplateSelfTest.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/robolectric-extension/src/test/kotlin/tech/apter/junit/jupiter/robolectric/RobolectricExtensionTestTemplateSelfTest.kt b/robolectric-extension/src/test/kotlin/tech/apter/junit/jupiter/robolectric/RobolectricExtensionTestTemplateSelfTest.kt index 35dde48..3521da6 100644 --- a/robolectric-extension/src/test/kotlin/tech/apter/junit/jupiter/robolectric/RobolectricExtensionTestTemplateSelfTest.kt +++ b/robolectric-extension/src/test/kotlin/tech/apter/junit/jupiter/robolectric/RobolectricExtensionTestTemplateSelfTest.kt @@ -15,7 +15,6 @@ import kotlin.test.assertEquals import kotlin.test.assertIs import kotlin.test.assertNotNull - @ExtendWith(RobolectricExtension::class) class RobolectricExtensionTestTemplateSelfTest {