[Gradle, JS] Generalization of Js test frameworks to work with ir

This commit is contained in:
Ilya Goncharov
2020-01-14 17:34:10 +03:00
parent 599215e74a
commit bf415704b6
7 changed files with 245 additions and 9 deletions
@@ -11,7 +11,6 @@ import org.gradle.language.base.plugins.LifecycleBasePlugin
import org.jetbrains.kotlin.gradle.plugin.AbstractKotlinTargetConfigurator import org.jetbrains.kotlin.gradle.plugin.AbstractKotlinTargetConfigurator
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.KotlinTargetWithTests import org.jetbrains.kotlin.gradle.plugin.KotlinTargetWithTests
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
import org.jetbrains.kotlin.gradle.plugin.whenEvaluated import org.jetbrains.kotlin.gradle.plugin.whenEvaluated
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsIrPlatformTestRun import org.jetbrains.kotlin.gradle.targets.js.KotlinJsIrPlatformTestRun
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsIrSubTargetDsl import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsIrSubTargetDsl
@@ -112,7 +111,7 @@ abstract class KotlinJsIrSubTarget(
} }
} }
private fun configureTestsRun(testRun: KotlinJsIrPlatformTestRun, compilation: KotlinJsCompilation) { private fun configureTestsRun(testRun: KotlinJsIrPlatformTestRun, compilation: KotlinJsIrCompilation) {
fun KotlinJsIrPlatformTestRun.subtargetTestTaskName(): String = disambiguateCamelCased( fun KotlinJsIrPlatformTestRun.subtargetTestTaskName(): String = disambiguateCamelCased(
lowerCamelCaseName( lowerCamelCaseName(
name.takeIf { it != KotlinTargetWithTests.DEFAULT_TEST_RUN_NAME }, name.takeIf { it != KotlinTargetWithTests.DEFAULT_TEST_RUN_NAME },
@@ -0,0 +1,127 @@
/*
* Copyright 2010-2019 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.gradle.targets.js.ir
import groovy.lang.Closure
import org.gradle.api.file.FileCollection
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.InputFiles
import org.gradle.api.tasks.Internal
import org.gradle.process.internal.DefaultProcessForkOptions
import org.gradle.util.ConfigureUtil
import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessagesTestExecutionSpec
import org.jetbrains.kotlin.gradle.targets.js.RequiredKotlinJsDependency
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin
import org.jetbrains.kotlin.gradle.targets.js.npm.LoadNpmModules
import org.jetbrains.kotlin.gradle.targets.js.npm.RequiresNpmDependencies
import org.jetbrains.kotlin.gradle.targets.js.npm.npmProject
import org.jetbrains.kotlin.gradle.targets.js.testing.karma.KotlinKarma
import org.jetbrains.kotlin.gradle.targets.js.testing.mocha.KotlinMocha
import org.jetbrains.kotlin.gradle.tasks.KotlinTest
open class KotlinJsIrTest :
KotlinTest(),
RequiresNpmDependencies,
LoadNpmModules {
private val nodeJs get() = NodeJsRootPlugin.apply(project.rootProject)
@get:Internal
internal var testFramework: KotlinJsIrTestFramework? = null
@Suppress("unused")
val testFrameworkSettings: String
@Input get() = testFramework!!.settingsState
@Input
var debug: Boolean = false
@Internal
override lateinit var compilation: KotlinJsIrCompilation
@Suppress("unused")
val runtimeClasspath: FileCollection
@InputFiles get() = compilation.runtimeDependencyFiles
@Suppress("unused")
internal val compilationOutputs: FileCollection
@InputFiles get() = compilation.output.allOutputs
@Suppress("unused")
val compilationId: String
@Input get() = compilation.let {
val target = it.target
target.project.path + "@" + target.name + ":" + it.compilationName
}
override val nodeModulesToLoad: List<String>
@Internal get() = listOf("./" + compilation.npmProject.main)
override val nodeModulesRequired: Boolean
@Internal get() = testFramework!!.nodeModulesRequired
override val requiredNpmDependencies: Collection<RequiredKotlinJsDependency>
@Internal get() = testFramework!!.requiredNpmDependencies
@Deprecated("Use useMocha instead", ReplaceWith("useMocha()"))
fun useNodeJs() = useMocha()
@Deprecated("Use useMocha instead", ReplaceWith("useMocha(body)"))
fun useNodeJs(body: KotlinMocha.() -> Unit) = useMocha(body)
@Deprecated("Use useMocha instead", ReplaceWith("useMocha(fn)"))
fun useNodeJs(fn: Closure<*>) {
useMocha {
ConfigureUtil.configure(fn, this)
}
}
fun useMocha() = useMocha {}
fun useMocha(body: KotlinMocha.() -> Unit) = use(KotlinMocha(compilation), body)
fun useMocha(fn: Closure<*>) {
useMocha {
ConfigureUtil.configure(fn, this)
}
}
fun useKarma() = useKarma {}
fun useKarma(body: KotlinKarma.() -> Unit) = use(KotlinKarma(compilation), body)
fun useKarma(fn: Closure<*>) {
useKarma {
ConfigureUtil.configure(fn, this)
}
}
private inline fun <T : KotlinJsIrTestFramework> use(runner: T, body: T.() -> Unit): T {
check(testFramework == null) {
"testFramework already configured for task ${this.path}"
}
val testFramework = runner.also(body)
this.testFramework = testFramework
return testFramework
}
override fun executeTests() {
nodeJs.npmResolutionManager.checkRequiredDependencies(this)
super.executeTests()
}
override fun createTestExecutionSpec(): TCServiceMessagesTestExecutionSpec {
val forkOptions = DefaultProcessForkOptions(fileResolver)
forkOptions.workingDir = compilation.npmProject.dir
forkOptions.executable = nodeJs.environment.nodeExecutable
val nodeJsArgs = mutableListOf<String>()
return testFramework!!.createTestExecutionSpec(
task = this,
forkOptions = forkOptions,
nodeJsArgs = nodeJsArgs,
debug = debug
)
}
}
@@ -0,0 +1,26 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. 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.gradle.targets.js.ir
import org.gradle.process.ProcessForkOptions
import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessagesTestExecutionSpec
import org.jetbrains.kotlin.gradle.targets.js.npm.RequiresNpmDependencies
interface KotlinJsIrTestFramework : RequiresNpmDependencies {
val settingsState: String
fun createTestExecutionSpec(
task: KotlinJsIrTest,
forkOptions: ProcessForkOptions,
nodeJsArgs: MutableList<String>,
debug: Boolean
): TCServiceMessagesTestExecutionSpec
/*
override val nodeModulesRequired: Boolean
get() = true
*/
}
@@ -0,0 +1,10 @@
/*
* Copyright 2010-2019 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.gradle.targets.js.npm
interface LoadNpmModules {
val nodeModulesToLoad: List<String>
}
@@ -16,13 +16,17 @@ import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessagesTestExecuti
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
import org.jetbrains.kotlin.gradle.targets.js.RequiredKotlinJsDependency import org.jetbrains.kotlin.gradle.targets.js.RequiredKotlinJsDependency
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin
import org.jetbrains.kotlin.gradle.targets.js.npm.LoadNpmModules
import org.jetbrains.kotlin.gradle.targets.js.npm.RequiresNpmDependencies import org.jetbrains.kotlin.gradle.targets.js.npm.RequiresNpmDependencies
import org.jetbrains.kotlin.gradle.targets.js.npm.npmProject import org.jetbrains.kotlin.gradle.targets.js.npm.npmProject
import org.jetbrains.kotlin.gradle.targets.js.testing.karma.KotlinKarma import org.jetbrains.kotlin.gradle.targets.js.testing.karma.KotlinKarma
import org.jetbrains.kotlin.gradle.targets.js.testing.mocha.KotlinMocha import org.jetbrains.kotlin.gradle.targets.js.testing.mocha.KotlinMocha
import org.jetbrains.kotlin.gradle.tasks.KotlinTest import org.jetbrains.kotlin.gradle.tasks.KotlinTest
open class KotlinJsTest : KotlinTest(), RequiresNpmDependencies { open class KotlinJsTest :
KotlinTest(),
RequiresNpmDependencies,
LoadNpmModules {
private val nodeJs get() = NodeJsRootPlugin.apply(project.rootProject) private val nodeJs get() = NodeJsRootPlugin.apply(project.rootProject)
@get:Internal @get:Internal
@@ -53,7 +57,7 @@ open class KotlinJsTest : KotlinTest(), RequiresNpmDependencies {
target.project.path + "@" + target.name + ":" + it.compilationName target.project.path + "@" + target.name + ":" + it.compilationName
} }
val nodeModulesToLoad: List<String> override val nodeModulesToLoad: List<String>
@Internal get() = listOf("./" + compilation.npmProject.main) @Internal get() = listOf("./" + compilation.npmProject.main)
override val nodeModulesRequired: Boolean override val nodeModulesRequired: Boolean
@@ -20,16 +20,23 @@ import org.jetbrains.kotlin.gradle.targets.js.NpmPackageVersion
import org.jetbrains.kotlin.gradle.targets.js.RequiredKotlinJsDependency import org.jetbrains.kotlin.gradle.targets.js.RequiredKotlinJsDependency
import org.jetbrains.kotlin.gradle.targets.js.appendConfigsFromDir import org.jetbrains.kotlin.gradle.targets.js.appendConfigsFromDir
import org.jetbrains.kotlin.gradle.targets.js.internal.parseNodeJsStackTraceAsJvm import org.jetbrains.kotlin.gradle.targets.js.internal.parseNodeJsStackTraceAsJvm
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTest
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTestFramework
import org.jetbrains.kotlin.gradle.targets.js.jsQuoted import org.jetbrains.kotlin.gradle.targets.js.jsQuoted
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin
import org.jetbrains.kotlin.gradle.targets.js.npm.LoadNpmModules
import org.jetbrains.kotlin.gradle.targets.js.npm.RequiresNpmDependencies
import org.jetbrains.kotlin.gradle.targets.js.npm.npmProject import org.jetbrains.kotlin.gradle.targets.js.npm.npmProject
import org.jetbrains.kotlin.gradle.targets.js.testing.* import org.jetbrains.kotlin.gradle.targets.js.testing.*
import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig
import org.jetbrains.kotlin.gradle.tasks.KotlinTest
import org.jetbrains.kotlin.gradle.testing.internal.reportsDir import org.jetbrains.kotlin.gradle.testing.internal.reportsDir
import org.slf4j.Logger import org.slf4j.Logger
import java.io.File import java.io.File
class KotlinKarma(override val compilation: KotlinJsCompilation) : KotlinJsTestFramework { class KotlinKarma(override val compilation: KotlinJsCompilation) :
KotlinJsTestFramework,
KotlinJsIrTestFramework {
private val project: Project = compilation.target.project private val project: Project = compilation.target.project
private val nodeJs = NodeJsRootPlugin.apply(project.rootProject) private val nodeJs = NodeJsRootPlugin.apply(project.rootProject)
private val versions = nodeJs.versions private val versions = nodeJs.versions
@@ -37,7 +44,7 @@ class KotlinKarma(override val compilation: KotlinJsCompilation) : KotlinJsTestF
private val config: KarmaConfig = KarmaConfig() private val config: KarmaConfig = KarmaConfig()
private val requiredDependencies = mutableSetOf<RequiredKotlinJsDependency>() private val requiredDependencies = mutableSetOf<RequiredKotlinJsDependency>()
private val configurators = mutableListOf<(KotlinJsTest) -> Unit>() private val configurators = mutableListOf<(KotlinTest) -> Unit>()
private val envJsCollector = mutableMapOf<String, String>() private val envJsCollector = mutableMapOf<String, String>()
private val confJsWriters = mutableListOf<(Appendable) -> Unit>() private val confJsWriters = mutableListOf<(Appendable) -> Unit>()
private var sourceMaps = false private var sourceMaps = false
@@ -269,12 +276,41 @@ class KotlinKarma(override val compilation: KotlinJsCompilation) : KotlinJsTestF
return adapterJs return adapterJs
} }
override fun createTestExecutionSpec(
task: KotlinJsIrTest,
forkOptions: ProcessForkOptions,
nodeJsArgs: MutableList<String>,
debug: Boolean
): TCServiceMessagesTestExecutionSpec =
createTestExecutionSpecPrivate(
task = task,
forkOptions = forkOptions,
nodeJsArgs = nodeJsArgs,
debug = debug
)
override fun createTestExecutionSpec( override fun createTestExecutionSpec(
task: KotlinJsTest, task: KotlinJsTest,
forkOptions: ProcessForkOptions, forkOptions: ProcessForkOptions,
nodeJsArgs: MutableList<String>, nodeJsArgs: MutableList<String>,
debug: Boolean debug: Boolean
): TCServiceMessagesTestExecutionSpec { ): TCServiceMessagesTestExecutionSpec =
createTestExecutionSpecPrivate(
task = task,
forkOptions = forkOptions,
nodeJsArgs = nodeJsArgs,
debug = debug
)
private fun <T> createTestExecutionSpecPrivate(
task: T,
forkOptions: ProcessForkOptions,
nodeJsArgs: MutableList<String>,
debug: Boolean
): TCServiceMessagesTestExecutionSpec
where T : KotlinTest,
T : RequiresNpmDependencies,
T : LoadNpmModules {
val npmProject = compilation.npmProject val npmProject = compilation.npmProject
val file = task.nodeModulesToLoad val file = task.nodeModulesToLoad
@@ -14,15 +14,22 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
import org.jetbrains.kotlin.gradle.targets.js.KotlinGradleNpmPackage import org.jetbrains.kotlin.gradle.targets.js.KotlinGradleNpmPackage
import org.jetbrains.kotlin.gradle.targets.js.RequiredKotlinJsDependency import org.jetbrains.kotlin.gradle.targets.js.RequiredKotlinJsDependency
import org.jetbrains.kotlin.gradle.targets.js.internal.parseNodeJsStackTraceAsJvm import org.jetbrains.kotlin.gradle.targets.js.internal.parseNodeJsStackTraceAsJvm
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTest
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTestFramework
import org.jetbrains.kotlin.gradle.targets.js.jsQuoted import org.jetbrains.kotlin.gradle.targets.js.jsQuoted
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin
import org.jetbrains.kotlin.gradle.targets.js.npm.LoadNpmModules
import org.jetbrains.kotlin.gradle.targets.js.npm.RequiresNpmDependencies
import org.jetbrains.kotlin.gradle.targets.js.npm.npmProject import org.jetbrains.kotlin.gradle.targets.js.npm.npmProject
import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest
import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTestFramework import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTestFramework
import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinTestRunnerCliArgs import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinTestRunnerCliArgs
import org.jetbrains.kotlin.gradle.tasks.KotlinTest
import java.io.File import java.io.File
class KotlinMocha(override val compilation: KotlinJsCompilation) : KotlinJsTestFramework { class KotlinMocha(override val compilation: KotlinJsCompilation) :
KotlinJsTestFramework,
KotlinJsIrTestFramework {
private val project: Project = compilation.target.project private val project: Project = compilation.target.project
private val nodeJs = NodeJsRootPlugin.apply(project.rootProject) private val nodeJs = NodeJsRootPlugin.apply(project.rootProject)
private val versions = nodeJs.versions private val versions = nodeJs.versions
@@ -40,12 +47,38 @@ class KotlinMocha(override val compilation: KotlinJsCompilation) : KotlinJsTestF
// https://mochajs.org/#-timeout-ms-t-ms // https://mochajs.org/#-timeout-ms-t-ms
var timeout: String = DEFAULT_TIMEOUT var timeout: String = DEFAULT_TIMEOUT
override fun createTestExecutionSpec(
task: KotlinJsIrTest,
forkOptions: ProcessForkOptions,
nodeJsArgs: MutableList<String>,
debug: Boolean
): TCServiceMessagesTestExecutionSpec =
createTestExecutionSpecPrivate<KotlinJsIrTest>(
task, forkOptions, nodeJsArgs, debug
)
override fun createTestExecutionSpec( override fun createTestExecutionSpec(
task: KotlinJsTest, task: KotlinJsTest,
forkOptions: ProcessForkOptions, forkOptions: ProcessForkOptions,
nodeJsArgs: MutableList<String>, nodeJsArgs: MutableList<String>,
debug: Boolean debug: Boolean
): TCServiceMessagesTestExecutionSpec { ): TCServiceMessagesTestExecutionSpec =
createTestExecutionSpecPrivate(
task = task,
forkOptions = forkOptions,
nodeJsArgs = nodeJsArgs,
debug = debug
)
private fun <T> createTestExecutionSpecPrivate(
task: T,
forkOptions: ProcessForkOptions,
nodeJsArgs: MutableList<String>,
debug: Boolean
): TCServiceMessagesTestExecutionSpec
where T : KotlinTest,
T : RequiresNpmDependencies,
T : LoadNpmModules {
val clientSettings = TCServiceMessagesClientSettings( val clientSettings = TCServiceMessagesClientSettings(
task.name, task.name,
testNameSuffix = task.targetName, testNameSuffix = task.targetName,
@@ -62,6 +95,7 @@ class KotlinMocha(override val compilation: KotlinJsCompilation) : KotlinJsTestF
exclude = task.excludePatterns exclude = task.excludePatterns
) )
val mocha = npmProject.require("mocha/bin/mocha") val mocha = npmProject.require("mocha/bin/mocha")
val file = task.nodeModulesToLoad val file = task.nodeModulesToLoad