Allow to mute JUnit 4 tests with parameters

This commit is contained in:
Nikolay Krasko
2019-12-20 02:24:42 +03:00
parent d74721716a
commit 8014a6509e
@@ -12,7 +12,6 @@ import org.junit.runners.parameterized.BlockJUnit4ClassRunnerWithParameters
import org.junit.runners.parameterized.ParametersRunnerFactory
import org.junit.runners.parameterized.TestWithParameters
import java.io.File
import java.lang.reflect.Method
private class AutoMute(
val file: String,
@@ -37,24 +36,44 @@ private class MutedTest(
@Suppress("unused") val issue: String?,
val hasFailFile: Boolean
) {
val methodName = key.substringAfterLast(".", "").replace("`", "").also {
if (it.isEmpty()) throw IllegalArgumentException("Can't get method name")
val methodKey: String
val classNameKey: String
val simpleClassName: String
init {
val noQuoteKey = key.replace("`", "")
val beforeParamsKey = noQuoteKey.substringBefore("[")
val params = noQuoteKey.substringAfterWithDelimiter("[", "")
methodKey = (beforeParamsKey.substringAfterLast(".", "") + params)
.also {
if (it.isEmpty()) throw IllegalArgumentException("Can't get method name")
}
classNameKey = beforeParamsKey.substringBeforeLast(".", "").also {
if (it.isEmpty()) throw IllegalArgumentException("Can't get class name")
}
simpleClassName = classNameKey.substringAfterLast(".")
}
val classNameKey = key.substringBeforeLast(".", "").also {
if (it.isEmpty()) throw IllegalArgumentException("Can't get class name")
companion object {
fun String.substringAfterWithDelimiter(delimiter: String, missingDelimiterValue: String = this): String {
val index = indexOf(delimiter)
return if (index == -1) missingDelimiterValue else (delimiter + substring(index + 1, length))
}
}
val simpleClassName = classNameKey.substringAfterLast(".")
}
private class MutedSet(muted: List<MutedTest>) {
// Method name -> Simple class name -> List of muted tests
// Method key -> Simple class name -> List of muted tests
private val cache: Map<String, Map<String, List<MutedTest>>> =
muted
.groupBy { it.methodName } // Method name -> List of muted tests
.groupBy { it.methodKey } // Method key -> List of muted tests
.mapValues { (_, tests) -> tests.groupBy { it.simpleClassName } }
fun mutedTest(testClass: Class<*>, methodName: String): MutedTest? {
val mutedTests = cache[methodName]?.get(testClass.simpleName) ?: return null
fun mutedTest(testClass: Class<*>, methodKey: String): MutedTest? {
val mutedTests = cache[methodKey]?.get(testClass.simpleName) ?: return null
return mutedTests.firstOrNull { mutedTest ->
testClass.canonicalName.endsWith(mutedTest.classNameKey)
@@ -85,14 +104,21 @@ private fun loadMutedTests(file: File): List<MutedTest> {
}
}
private val MUTE_LINE_PARSE_REGEXP = Regex("^([^,\\[]+)(\\[[^]]+])?(,\\s*)?([^,]+)?(,\\s*)?([^,]+)?$")
private fun parseMutedTest(str: String): MutedTest {
val components = str.splitToSequence(",").map { it.trim() }.toList()
val matchResult = MUTE_LINE_PARSE_REGEXP.matchEntire(str) ?: throw ParseError("Can't parse the line: $str")
val key = components.getOrNull(0) ?: throw ParseError("Test key is absent (1 column): $str")
val methodFull = matchResult.groups[1]?.value ?: throw ParseError("Test key is absent (1 column): $str")
val params = matchResult.groups[2]?.value ?: ""
val issue = components.getOrNull(1)
val key = methodFull + params
val hasFailFile = when (val stateStr = components.getOrNull(2)) {
val issue = matchResult.groups[4]?.value
val stateStr = matchResult.groups[6]?.value
val hasFailFile = when (stateStr) {
"MUTE", "", null -> false
"FAIL" -> true
else -> throw ParseError("Invalid state (`$stateStr`), MUTE, FAIL or empty are expected: $str")
@@ -115,12 +141,8 @@ internal fun isMutedInDatabase(testCase: TestCase): Boolean {
return isMutedInDatabase(testCase.javaClass, testCase.name)
}
fun isMutedInDatabase(method: Method): Boolean {
return isMutedInDatabase(method.declaringClass, method.name)
}
fun isMutedInDatabase(testClass: Class<*>, methodName: String): Boolean {
val mutedTest = mutedSet.mutedTest(testClass, methodName)
fun isMutedInDatabase(testClass: Class<*>, methodKey: String): Boolean {
val mutedTest = mutedSet.mutedTest(testClass, methodKey)
return mutedTest != null && !mutedTest.hasFailFile
}
@@ -152,22 +174,28 @@ internal fun wrapWithMuteInDatabase(testCase: TestCase, f: () -> Unit): (() -> U
private fun mutedMessage(key: String) = "MUTED TEST: $key"
private fun testKey(testCase: TestCase) = "${testCase::class.java.canonicalName}.${testCase.name}"
private fun testKey(method: Method) = "${method.declaringClass.canonicalName}.${method.name}"
private fun testKey(klass: Class<*>, methodKey: String) = "${klass.canonicalName}.$methodKey"
private fun testKey(testCase: TestCase) = testKey(testCase::class.java, testCase.name)
class RunnerFactoryWithMuteInDatabase: ParametersRunnerFactory {
override fun createRunnerForTestWithParameters(test: TestWithParameters?): Runner {
return object : BlockJUnit4ClassRunnerWithParameters(test) {
override fun isIgnored(child: FrameworkMethod): Boolean {
return super.isIgnored(child) || isIgnoredInDatabaseWithLog(child)
return super.isIgnored(child) || isIgnoredInDatabaseWithLog(child, name)
}
}
}
}
fun isIgnoredInDatabaseWithLog(child: FrameworkMethod): Boolean {
if (isMutedInDatabase(child.method)) {
System.err.println(mutedMessage(testKey(child.method)))
fun isIgnoredInDatabaseWithLog(child: FrameworkMethod, parametersName: String): Boolean {
if (isMutedInDatabase(child.declaringClass, child.name)) {
System.err.println(mutedMessage(testKey(child.declaringClass, child.name)))
return true
}
val methodWithParametersKey = child.method.name + parametersName
if (isMutedInDatabase(child.declaringClass, methodWithParametersKey)) {
System.err.println(mutedMessage(testKey(child.declaringClass, methodWithParametersKey)))
return true
}