[Test] Add ability to mark group of tests with specific tags
Currently tags can be applied to all tests in specific testdata directory by placing `_tags.txt` file in it, where all tags should be listed on separate lines. Test generator adds those tags to corresponding generated test classes with `@Tag` annotation Please note that is applicable only to JUnit 5 tests
This commit is contained in:
committed by
teamcityserver
parent
b9c549803d
commit
c2e2068682
+24
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.test.TestMetadata
|
|||||||
import org.jetbrains.kotlin.test.util.KtTestUtil
|
import org.jetbrains.kotlin.test.util.KtTestUtil
|
||||||
import org.jetbrains.kotlin.utils.Printer
|
import org.jetbrains.kotlin.utils.Printer
|
||||||
import org.junit.jupiter.api.Nested
|
import org.junit.jupiter.api.Nested
|
||||||
|
import org.junit.jupiter.api.Tag
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
@@ -64,6 +65,12 @@ object NewTestGeneratorImpl : TestGenerator(METHOD_GENERATORS) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun Printer.generateTags(testEntityModel: TestEntityModel) {
|
||||||
|
for (tag in testEntityModel.tags) {
|
||||||
|
println("@Tag(\"$tag\")")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun Printer.generateSuppressAllWarnings() {
|
private fun Printer.generateSuppressAllWarnings() {
|
||||||
println("@SuppressWarnings(\"all\")")
|
println("@SuppressWarnings(\"all\")")
|
||||||
}
|
}
|
||||||
@@ -134,6 +141,9 @@ object NewTestGeneratorImpl : TestGenerator(METHOD_GENERATORS) {
|
|||||||
p.println("import ${TestMetadata::class.java.canonicalName};")
|
p.println("import ${TestMetadata::class.java.canonicalName};")
|
||||||
p.println("import ${Nested::class.java.canonicalName};")
|
p.println("import ${Nested::class.java.canonicalName};")
|
||||||
p.println("import ${Test::class.java.canonicalName};")
|
p.println("import ${Test::class.java.canonicalName};")
|
||||||
|
if (testClassModels.any { it.containsTags() }) {
|
||||||
|
p.println("import ${Tag::class.java.canonicalName};")
|
||||||
|
}
|
||||||
p.println()
|
p.println()
|
||||||
p.println("import java.io.File;")
|
p.println("import java.io.File;")
|
||||||
p.println("import java.util.regex.Pattern;")
|
p.println("import java.util.regex.Pattern;")
|
||||||
@@ -173,6 +183,9 @@ object NewTestGeneratorImpl : TestGenerator(METHOD_GENERATORS) {
|
|||||||
|
|
||||||
override val imports: Set<Class<*>>
|
override val imports: Set<Class<*>>
|
||||||
get() = super.imports
|
get() = super.imports
|
||||||
|
|
||||||
|
override val tags: List<String>
|
||||||
|
get() = emptyList()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,6 +195,7 @@ object NewTestGeneratorImpl : TestGenerator(METHOD_GENERATORS) {
|
|||||||
|
|
||||||
private fun generateTestClass(p: Printer, testClassModel: TestClassModel, isNested: Boolean) {
|
private fun generateTestClass(p: Printer, testClassModel: TestClassModel, isNested: Boolean) {
|
||||||
p.generateNestedAnnotation(isNested)
|
p.generateNestedAnnotation(isNested)
|
||||||
|
p.generateTags(testClassModel)
|
||||||
p.generateMetadata(testClassModel)
|
p.generateMetadata(testClassModel)
|
||||||
p.generateTestDataPath(testClassModel)
|
p.generateTestDataPath(testClassModel)
|
||||||
p.generateParameterAnnotations(testClassModel)
|
p.generateParameterAnnotations(testClassModel)
|
||||||
@@ -229,6 +243,7 @@ object NewTestGeneratorImpl : TestGenerator(METHOD_GENERATORS) {
|
|||||||
val generator = methodGenerators.getValue(methodModel.kind)
|
val generator = methodGenerators.getValue(methodModel.kind)
|
||||||
|
|
||||||
p.generateTestAnnotation()
|
p.generateTestAnnotation()
|
||||||
|
p.generateTags(methodModel)
|
||||||
p.generateMetadata(methodModel)
|
p.generateMetadata(methodModel)
|
||||||
generator.hackyGenerateSignature(methodModel, p)
|
generator.hackyGenerateSignature(methodModel, p)
|
||||||
p.printWithNoIndent(" {")
|
p.printWithNoIndent(" {")
|
||||||
@@ -252,4 +267,13 @@ object NewTestGeneratorImpl : TestGenerator(METHOD_GENERATORS) {
|
|||||||
generateSignature(method as T, p)
|
generateSignature(method as T, p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun TestEntityModel.containsTags(): Boolean {
|
||||||
|
if (this.tags.isNotEmpty()) return true
|
||||||
|
if (this is TestClassModel) {
|
||||||
|
if (innerTestClasses.any { it.containsTags() }) return true
|
||||||
|
if (methods.any { it.containsTags() }) return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -176,6 +176,9 @@ private class TestGeneratorImplInstance(
|
|||||||
|
|
||||||
override val imports: Set<Class<*>>
|
override val imports: Set<Class<*>>
|
||||||
get() = super.imports
|
get() = super.imports
|
||||||
|
|
||||||
|
override val tags: List<String>
|
||||||
|
get() = emptyList()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-2
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.generators
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.generators.model.*
|
import org.jetbrains.kotlin.generators.model.*
|
||||||
import org.jetbrains.kotlin.generators.util.TestGeneratorUtil
|
import org.jetbrains.kotlin.generators.util.TestGeneratorUtil
|
||||||
|
import org.jetbrains.kotlin.generators.util.extractTagsFromDirectory
|
||||||
import org.jetbrains.kotlin.test.TargetBackend
|
import org.jetbrains.kotlin.test.TargetBackend
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@@ -116,13 +117,15 @@ class TestGroup(
|
|||||||
|
|
||||||
SingleClassTestModel(
|
SingleClassTestModel(
|
||||||
rootFile, compiledPattern, compiledExcludedPattern, filenameStartsLowerCase, testMethod, className,
|
rootFile, compiledPattern, compiledExcludedPattern, filenameStartsLowerCase, testMethod, className,
|
||||||
realTargetBackend, skipIgnored, testRunnerMethodName, additionalRunnerArguments, annotations
|
realTargetBackend, skipIgnored, testRunnerMethodName, additionalRunnerArguments, annotations,
|
||||||
|
extractTagsFromDirectory(rootFile)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
SimpleTestClassModel(
|
SimpleTestClassModel(
|
||||||
rootFile, recursive, excludeParentDirs,
|
rootFile, recursive, excludeParentDirs,
|
||||||
compiledPattern, compiledExcludedPattern, filenameStartsLowerCase, testMethod, className,
|
compiledPattern, compiledExcludedPattern, filenameStartsLowerCase, testMethod, className,
|
||||||
realTargetBackend, excludeDirs, skipIgnored, testRunnerMethodName, additionalRunnerArguments, deep, annotations
|
realTargetBackend, excludeDirs, skipIgnored, testRunnerMethodName, additionalRunnerArguments, deep, annotations,
|
||||||
|
extractTagsFromDirectory(rootFile)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
+3
@@ -25,4 +25,7 @@ open class DelegatingTestClassModel(private val delegate: TestClassModel) : Test
|
|||||||
|
|
||||||
override val annotations: Collection<AnnotationModel>
|
override val annotations: Collection<AnnotationModel>
|
||||||
get() = delegate.annotations
|
get() = delegate.annotations
|
||||||
|
|
||||||
|
override val tags: List<String>
|
||||||
|
get() = delegate.tags
|
||||||
}
|
}
|
||||||
|
|||||||
+3
@@ -21,6 +21,9 @@ class RunTestMethodModel(
|
|||||||
override val name = METHOD_NAME
|
override val name = METHOD_NAME
|
||||||
override val dataString: String? = null
|
override val dataString: String? = null
|
||||||
|
|
||||||
|
override val tags: List<String>
|
||||||
|
get() = emptyList()
|
||||||
|
|
||||||
override fun imports(): Collection<Class<*>> {
|
override fun imports(): Collection<Class<*>> {
|
||||||
return super.imports() + if (isWithTargetBackend()) setOf(TargetBackend::class.java) else emptySet()
|
return super.imports() + if (isWithTargetBackend()) setOf(TargetBackend::class.java) else emptySet()
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-2
@@ -6,6 +6,8 @@ package org.jetbrains.kotlin.generators.model
|
|||||||
|
|
||||||
import com.intellij.openapi.util.io.FileUtil
|
import com.intellij.openapi.util.io.FileUtil
|
||||||
import org.jetbrains.kotlin.generators.util.TestGeneratorUtil.fileNameToJavaIdentifier
|
import org.jetbrains.kotlin.generators.util.TestGeneratorUtil.fileNameToJavaIdentifier
|
||||||
|
import org.jetbrains.kotlin.generators.util.extractTagsFromDirectory
|
||||||
|
import org.jetbrains.kotlin.generators.util.extractTagsFromTestFile
|
||||||
import org.jetbrains.kotlin.test.TargetBackend
|
import org.jetbrains.kotlin.test.TargetBackend
|
||||||
import org.jetbrains.kotlin.test.util.KtTestUtil
|
import org.jetbrains.kotlin.test.util.KtTestUtil
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@@ -28,6 +30,7 @@ class SimpleTestClassModel(
|
|||||||
private val additionalRunnerArguments: List<String>,
|
private val additionalRunnerArguments: List<String>,
|
||||||
private val deep: Int?,
|
private val deep: Int?,
|
||||||
override val annotations: Collection<AnnotationModel>,
|
override val annotations: Collection<AnnotationModel>,
|
||||||
|
override val tags: List<String>
|
||||||
) : TestClassModel() {
|
) : TestClassModel() {
|
||||||
override val name: String
|
override val name: String
|
||||||
get() = testClassName
|
get() = testClassName
|
||||||
@@ -60,6 +63,7 @@ class SimpleTestClassModel(
|
|||||||
additionalRunnerArguments,
|
additionalRunnerArguments,
|
||||||
if (deep != null) deep - 1 else null,
|
if (deep != null) deep - 1 else null,
|
||||||
annotations,
|
annotations,
|
||||||
|
extractTagsFromDirectory(file)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -85,7 +89,13 @@ class SimpleTestClassModel(
|
|||||||
if (!rootFile.isDirectory) {
|
if (!rootFile.isDirectory) {
|
||||||
return@lazy listOf(
|
return@lazy listOf(
|
||||||
SimpleTestMethodModel(
|
SimpleTestMethodModel(
|
||||||
rootFile, rootFile, filenamePattern, checkFilenameStartsLowerCase, targetBackend, skipIgnored
|
rootFile,
|
||||||
|
rootFile,
|
||||||
|
filenamePattern,
|
||||||
|
checkFilenameStartsLowerCase,
|
||||||
|
targetBackend,
|
||||||
|
skipIgnored,
|
||||||
|
extractTagsFromTestFile(rootFile)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -103,7 +113,7 @@ class SimpleTestClassModel(
|
|||||||
result.add(
|
result.add(
|
||||||
SimpleTestMethodModel(
|
SimpleTestMethodModel(
|
||||||
rootFile, file, filenamePattern,
|
rootFile, file, filenamePattern,
|
||||||
checkFilenameStartsLowerCase, targetBackend, skipIgnored
|
checkFilenameStartsLowerCase, targetBackend, skipIgnored, extractTagsFromTestFile(file)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -143,6 +153,9 @@ class SimpleTestClassModel(
|
|||||||
override fun shouldBeGenerated(): Boolean {
|
override fun shouldBeGenerated(): Boolean {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override val tags: List<String>
|
||||||
|
get() = emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
+2
-1
@@ -18,7 +18,8 @@ open class SimpleTestMethodModel(
|
|||||||
private val filenamePattern: Pattern,
|
private val filenamePattern: Pattern,
|
||||||
checkFilenameStartsLowerCase: Boolean?,
|
checkFilenameStartsLowerCase: Boolean?,
|
||||||
protected val targetBackend: TargetBackend,
|
protected val targetBackend: TargetBackend,
|
||||||
private val skipIgnored: Boolean
|
private val skipIgnored: Boolean,
|
||||||
|
override val tags: List<String>
|
||||||
) : MethodModel {
|
) : MethodModel {
|
||||||
object Kind : MethodModel.Kind()
|
object Kind : MethodModel.Kind()
|
||||||
|
|
||||||
|
|||||||
+6
-2
@@ -22,7 +22,8 @@ class SingleClassTestModel(
|
|||||||
private val skipIgnored: Boolean,
|
private val skipIgnored: Boolean,
|
||||||
private val testRunnerMethodName: String,
|
private val testRunnerMethodName: String,
|
||||||
private val additionalRunnerArguments: List<String>,
|
private val additionalRunnerArguments: List<String>,
|
||||||
override val annotations: List<AnnotationModel>
|
override val annotations: List<AnnotationModel>,
|
||||||
|
override val tags: List<String>
|
||||||
) : TestClassModel() {
|
) : TestClassModel() {
|
||||||
override val name: String
|
override val name: String
|
||||||
get() = testClassName
|
get() = testClassName
|
||||||
@@ -46,7 +47,7 @@ class SingleClassTestModel(
|
|||||||
private fun getTestMethodsFromFile(file: File): Collection<MethodModel> {
|
private fun getTestMethodsFromFile(file: File): Collection<MethodModel> {
|
||||||
return listOf(
|
return listOf(
|
||||||
SimpleTestMethodModel(
|
SimpleTestMethodModel(
|
||||||
rootFile, file, filenamePattern, checkFilenameStartsLowerCase, targetBackend, skipIgnored
|
rootFile, file, filenamePattern, checkFilenameStartsLowerCase, targetBackend, skipIgnored, tags = emptyList()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -73,5 +74,8 @@ class SingleClassTestModel(
|
|||||||
override fun shouldBeGenerated(): Boolean {
|
override fun shouldBeGenerated(): Boolean {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override val tags: List<String>
|
||||||
|
get() = emptyList()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.generators.model
|
|||||||
interface TestEntityModel {
|
interface TestEntityModel {
|
||||||
val name: String
|
val name: String
|
||||||
val dataString: String?
|
val dataString: String?
|
||||||
|
val tags: List<String>
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ClassModel : TestEntityModel {
|
interface ClassModel : TestEntityModel {
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.generators.util
|
||||||
|
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
private const val TAGS_FILE_NAME = "_tags.txt"
|
||||||
|
private val PROHIBITED_SYMBOLS = listOf(' ', ',', '(', ')', '&', '|', '!')
|
||||||
|
|
||||||
|
fun extractTagsFromDirectory(dir: File): List<String> {
|
||||||
|
require(dir.isDirectory)
|
||||||
|
val tagsFile = dir.resolve(TAGS_FILE_NAME)
|
||||||
|
if (!tagsFile.exists()) return emptyList()
|
||||||
|
return tagsFile.readLines().filter { it.isNotBlank() }.onEach(::validateTag)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: support tags in testdata files
|
||||||
|
fun extractTagsFromTestFile(@Suppress("UNUSED_PARAMETER") file: File): List<String> = emptyList()
|
||||||
|
|
||||||
|
private fun validateTag(tag: String) {
|
||||||
|
require(PROHIBITED_SYMBOLS.none { it in tag }) {
|
||||||
|
"Tag \"tag\" contains one of prohibited symbols: $PROHIBITED_SYMBOLS"
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user