All Downloads are FREE. Search and download functionalities are using the official Maven repository.

main.name.remal.gradle_plugins.plugins.testing.RandomizeTestClassesPlugin.kt Maven / Gradle / Ivy

There is a newer version: 1.9.2
Show newest version
package name.remal.gradle_plugins.plugins.testing

import name.remal.gradle_plugins.dsl.BaseReflectiveProjectPlugin
import name.remal.gradle_plugins.dsl.CreateExtensionsPluginAction
import name.remal.gradle_plugins.dsl.Plugin
import name.remal.gradle_plugins.dsl.PluginAction
import name.remal.gradle_plugins.dsl.SimpleTestAdditionalGradleScript
import name.remal.gradle_plugins.dsl.extensions.all
import name.remal.gradle_plugins.dsl.extensions.doFirstOrdered
import name.remal.gradle_plugins.dsl.extensions.get
import name.remal.gradle_plugins.dsl.extensions.logLifecycle
import name.remal.gradle_plugins.dsl.extensions.randomizeFileTree
import org.gradle.api.Project
import org.gradle.api.plugins.ExtensionContainer
import org.gradle.api.tasks.TaskContainer
import org.gradle.api.tasks.testing.Test
import java.util.Random

private const val PLUGIN_ID = "name.remal.randomize-test-classes"

@Plugin(
    id = PLUGIN_ID,
    description = "Plugin that randomizes test classes for every Test task run.",
    tags = ["test", "random"]
)
@SimpleTestAdditionalGradleScript(
    """
    apply plugin: 'java'

    dependencies {
        testImplementation "junit:junit:4.12"
    }

    List testClasses = (1..9).collect { "name.remal.test.TestClass${'$'}it" }

    File executedTestClassesFile = file(".executed-classes")
    executedTestClassesFile.parentFile.mkdirs()
    executedTestClassesFile.delete()

    test {
        useJUnit()
        forkEvery = 0
        maxParallelForks = 1

        doLast {
            if (!executedTestClassesFile.isFile()) {
                throw new AssertionError("${'$'}executedTestClassesFile is not a file")
            }

            List executedTestClasses = executedTestClassesFile.readLines("UTF-8")
                .collect { it.trim() }
                .findAll { !it.isEmpty() }

            if (executedTestClasses == testClasses) {
                throw new AssertionError("${'$'}executedTestClasses == ${'$'}testClasses")
            }
            if (executedTestClasses.size() != testClasses.size()) {
                throw new AssertionError("executedTestClasses.size() != testClasses.size()")
            }
        }
    }

    testClassesRandomization {
        seed = 1
    }

    testClasses.forEach { className ->
        project.file("src/test/java/${'$'}{className.replace('.', '/')}.java").with {
            parentFile.mkdirs()
            newWriter().withCloseable {
                it.println "package ${'$'}{className.substring(0, className.lastIndexOf('.'))};"
                it.println ""
                it.println "import java.io.File;"
                it.println ""
                it.println "import org.junit.Test;"
                it.println ""
                it.println "import static java.nio.file.Files.*;"
                it.println "import static java.nio.file.StandardOpenOption.*;"
                it.println "import static java.util.Arrays.*;"
                it.println ""
                it.println "public class ${'$'}{className.substring(className.lastIndexOf('.') + 1)} {"
                it.println ""
                it.println "    @Test"
                it.println "    public void test() throws Throwable {"
                it.println "        write(new File(\"${'$'}{executedTestClassesFile.absolutePath.replace('\\', '\\\\')}\").toPath(), asList(\"${'$'}className\"), CREATE, APPEND);"
                it.println "    }"
                it.println ""
                it.println "}"
            }
        }
    }
"""
)
class RandomizeTestClassesPlugin : BaseReflectiveProjectPlugin() {

    @CreateExtensionsPluginAction
    fun ExtensionContainer.`Create 'testClassesRandomization' extension`(project: Project) {
        create("testClassesRandomization", RandomizeTestClassesExtension::class.java, project)
    }

    @PluginAction
    fun TaskContainer.`Process all Test tasks`(extensions: ExtensionContainer) {
        val settings = extensions[RandomizeTestClassesExtension::class.java]
        val seed: Long by lazy { settings.seed }

        all(Test::class.java) {
            it.doFirstOrdered { task ->
                if (!settings.enabled) {
                    logger.debug("Test classes randomization is disabled")
                    return@doFirstOrdered
                }

                task.logLifecycle("Plugin {}: randomizing test classes using seed {}", pluginId, seed)
                task.testClassesDirs = task.project.randomizeFileTree(task.candidateClassFiles, Random(seed))
            }
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy