Add support for tests mute-in database in JUnit 5.

^KT-45744 In Progress
This commit is contained in:
Yahor Berdnikau
2021-03-24 16:07:32 +01:00
committed by TeamCityServer
parent 7ffdafe791
commit 8b393910d3
3 changed files with 104 additions and 0 deletions
+1
View File
@@ -97,6 +97,7 @@ dependencies {
testCompile(intellijDep()) { includeJars("platform-util-ui", "platform-concurrency", "platform-objectSerializer") }
testCompile(intellijDep()) { includeJars("platform-ide-util-io") }
testApiJUnit5()
}
tasks.withType<org.jetbrains.kotlin.gradle.dsl.KotlinCompile<*>> {
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.test
import junit.framework.TestCase
import org.jetbrains.kotlin.test.mutes.*
import org.junit.internal.runners.statements.InvokeMethod
import org.junit.jupiter.api.extension.*
import org.junit.runner.Runner
import org.junit.runner.notification.RunNotifier
import org.junit.runners.BlockJUnit4ClassRunner
@@ -16,6 +17,7 @@ import org.junit.runners.model.Statement
import org.junit.runners.parameterized.BlockJUnit4ClassRunnerWithParameters
import org.junit.runners.parameterized.ParametersRunnerFactory
import org.junit.runners.parameterized.TestWithParameters
import java.lang.reflect.Method
internal fun wrapWithMuteInDatabase(testCase: TestCase, f: () -> Unit): (() -> Unit)? {
return wrapWithMuteInDatabase(testCase.javaClass, testCase.name, f)
@@ -95,3 +97,102 @@ fun TestCase.runTest(test: () -> Unit) {
}
annotation class WithMutedInDatabaseRunTest
/**
* Extension for JUnit 5 tests adding mute-in database support to ignore flaky/failed tests.
*
* Just add it to the test class or test method.
*/
@Target(AnnotationTarget.CLASS, AnnotationTarget.ANNOTATION_CLASS, AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
@ExtendWith(MuteInCondition::class, MuteInTestWatcher::class, MuteInInvocationInterceptor::class)
annotation class WithMuteInDatabase
private val ExtensionContext.testClassNullable get() = testClass.orElseGet { null }
private val ExtensionContext.testMethodNullable get() = testMethod.orElseGet { null }
class MuteInCondition : ExecutionCondition {
override fun evaluateExecutionCondition(
context: ExtensionContext
): ConditionEvaluationResult {
val testClass = context.testClassNullable
val testMethod = context.testMethodNullable
return if (testClass != null &&
testMethod != null &&
isMutedInDatabaseWithLog(testClass, testMethod.name)
) {
ConditionEvaluationResult.disabled("Muted")
} else {
enabled
}
}
companion object {
private val enabled = ConditionEvaluationResult.enabled("Not found in mute-in database")
}
}
class MuteInTestWatcher : TestWatcher {
override fun testFailed(
context: ExtensionContext,
cause: Throwable
) {
val testClass = context.testClassNullable
val testMethod = context.testMethodNullable
if (testClass != null &&
testMethod != null
) {
DO_AUTO_MUTE?.muteTest(
testKey(testClass, testMethod.name)
)
}
}
}
class MuteInInvocationInterceptor : InvocationInterceptor {
override fun interceptTestTemplateMethod(
invocation: InvocationInterceptor.Invocation<Void>,
invocationContext: ReflectiveInvocationContext<Method>,
extensionContext: ExtensionContext
) {
interceptWithMuteInDatabase(invocation, extensionContext)
}
override fun interceptTestMethod(
invocation: InvocationInterceptor.Invocation<Void>,
invocationContext: ReflectiveInvocationContext<Method>,
extensionContext: ExtensionContext
) {
interceptWithMuteInDatabase(invocation, extensionContext)
}
private fun interceptWithMuteInDatabase(
invocation: InvocationInterceptor.Invocation<Void>,
extensionContext: ExtensionContext
) {
val testClass = extensionContext.testClassNullable
val testMethod = extensionContext.testMethodNullable
if (testClass != null &&
testMethod != null
) {
val mutedTest = getMutedTest(testClass, testMethod.name)
if (mutedTest != null &&
isPresentedInDatabaseWithoutFailMarker(mutedTest)
) {
if (mutedTest.isFlaky) {
invocation.proceed()
return
} else {
invertMutedTestResultWithLog(
f = { invocation.proceed() },
testKey = testKey(testMethod.declaringClass, mutedTest.methodKey)
)
return
}
}
}
invocation.proceed()
}
}
@@ -11,6 +11,7 @@ import org.gradle.internal.impldep.org.junit.platform.commons.support.Annotation
import org.gradle.util.GradleVersion
import org.jetbrains.kotlin.gradle.KOTLIN_VERSION
import org.jetbrains.kotlin.gradle.utils.minSupportedGradleVersion
import org.jetbrains.kotlin.test.WithMuteInDatabase
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance
@@ -28,6 +29,7 @@ import kotlin.streams.asStream
* Base class for all Kotlin Gradle plugin integration tests.
*/
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@WithMuteInDatabase
abstract class KGPBaseTest {
open val defaultBuildOptions = BuildOptions()