Add support for tests mute-in database in JUnit 5.
^KT-45744 In Progress
This commit is contained in:
committed by
TeamCityServer
parent
7ffdafe791
commit
8b393910d3
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
+2
@@ -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()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user