Gradle: Basic Kotlin NodeJS tests runner

#KT-30531 Fixed
#KT-30528 Fixed
This commit is contained in:
Sergey Rostov
2019-02-20 15:14:05 +03:00
parent b6e675f934
commit d467e4209a
54 changed files with 3968 additions and 64 deletions
@@ -23,6 +23,7 @@ dependencies {
testCompile(project(":kotlin-test:kotlin-test-jvm"))
testCompile(projectRuntimeJar(":kotlin-compiler-embeddable"))
testCompile(intellijCoreDep()) { includeJars("jdom") }
// testCompileOnly dependency on non-shaded artifacts is needed for IDE support
// testRuntime on shaded artifact is needed for running tests with shaded compiler
testCompileOnly(project(path = ":kotlin-gradle-plugin-test-utils-embeddable", configuration = "compile"))
@@ -1,9 +1,13 @@
package org.jetbrains.kotlin.gradle
import com.intellij.testFramework.TestDataFile
import org.gradle.api.logging.LogLevel
import org.gradle.tooling.GradleConnector
import org.gradle.util.GradleVersion
import org.gradle.util.VersionNumber
import org.jdom.Element
import org.jdom.input.SAXBuilder
import org.jdom.output.Format
import org.jdom.output.XMLOutputter
import org.jetbrains.kotlin.gradle.model.ModelContainer
import org.jetbrains.kotlin.gradle.model.ModelFetcherBuildAction
import org.jetbrains.kotlin.gradle.util.*
@@ -495,6 +499,23 @@ abstract class BaseGradleIT {
}
}
fun CompiledProject.assertTasksRegistered(vararg tasks: String) {
for (task in tasks) {
assertContains("'Register task $task'")
}
}
fun CompiledProject.assertTasksNotRealized(vararg tasks: String) {
for (task in tasks) {
assertNotContains("'Realize task $task'")
}
}
fun CompiledProject.assertTasksRegisteredAndNotRealized(vararg tasks: String) {
assertTasksRegistered(*tasks)
assertTasksNotRealized(*tasks)
}
fun CompiledProject.getOutputForTask(taskName: String): String {
val taskOutputRegex = ("(?:\\[LIFECYCLE] \\[class org\\.gradle(?:\\.internal\\.buildevents)?\\.TaskExecutionLogger] :$taskName|" +
"\\[org\\.gradle\\.execution\\.plan\\.DefaultPlanExecutor\\] :$taskName.*?started)" +
@@ -575,6 +596,71 @@ abstract class BaseGradleIT {
File(projectDir, it).takeIf(File::exists)
}.single()
/**
* @param assertionFileName path to xml with expected test results, relative to test resources root
*/
fun CompiledProject.assertTestResults(
@TestDataFile assertionFileName: String,
testReportName: String
) {
val projectDir = project.projectDir
val testReportDir = projectDir.resolve("build/test-results/$testReportName")
if (!testReportDir.isDirectory) {
error("Test report dir was not created")
}
val actualTestResults = readAndCleanupTestResults(testReportDir, projectDir)
val expectedTestResults = resourcesRootFile.resolve(assertionFileName).readText()
assertEquals(
prettyPrintXml(expectedTestResults),
prettyPrintXml(actualTestResults)
)
}
private fun readAndCleanupTestResults(testReportDir: File, projectDir: File): String {
val files = testReportDir
.listFiles()
.filter { it.isFile && it.name.endsWith(".xml") }
.sortedBy {
// let containing test suite be first
it.name.replace(".xml", ".A.xml")
}
val xmlString = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<results>\n" +
files.joinToString("") {
it.readText()
.replace(projectDir.absolutePath, "/\$PROJECT_DIR$")
.replace(projectDir.name, "\$PROJECT_NAME$")
.replace("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n", "")
} +
"</results>"
val doc = SAXBuilder().build(xmlString.reader())
val skipAttrs = setOf("timestamp", "hostname", "time", "message")
val skipContentsOf = setOf("failure")
fun cleanup(e: Element) {
if (e.name in skipContentsOf) e.text = "..."
e.attributes.forEach {
if (it.name in skipAttrs) {
it.value = "..."
}
}
e.children.forEach {
cleanup(it)
}
}
cleanup(doc.rootElement)
return XMLOutputter(Format.getPrettyFormat()).outputString(doc)
}
private fun prettyPrintXml(uglyXml: String): String =
XMLOutputter(Format.getPrettyFormat()).outputString(SAXBuilder().build(uglyXml.reader()))
private fun Project.createGradleTailParameters(options: BuildOptions, params: Array<out String> = arrayOf()): List<String> =
params.toMutableList().apply {
add("--stacktrace")
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.gradle
import com.intellij.testFramework.TestDataPath
import org.jetbrains.kotlin.gradle.plugin.EXPECTED_BY_CONFIG_NAME
import org.jetbrains.kotlin.gradle.plugin.IMPLEMENT_CONFIG_NAME
import org.jetbrains.kotlin.gradle.plugin.IMPLEMENT_DEPRECATION_WARNING
@@ -25,6 +26,7 @@ import org.junit.Test
import java.io.File
import kotlin.test.assertTrue
@TestDataPath("\$CONTENT_ROOT/resources")
class MultiplatformGradleIT : BaseGradleIT() {
@Test
@@ -293,4 +295,81 @@ class MultiplatformGradleIT : BaseGradleIT() {
assertTasksExecuted(customSourceSetCompileTasks)
}
}
@Test
fun testMppNodeJsTestRun() = with(Project("new-mpp-js-tests", GradleVersionRequired.AtLeast("4.10.2"))) {
setupWorkingDir()
gradleBuildScript().modify(::transformBuildScriptWithPluginsDsl)
gradleSettingsScript().modify(::transformBuildScriptWithPluginsDsl)
// just build without running tests to check configuration avoidance
build("assemble") {
assertSuccessful()
assertTasksRegisteredAndNotRealized(
":clientKotlinJsNodeModules",
":clientKotlinJsNodeModulesTestRuntime",
":clientTest",
":serverKotlinJsNodeModules",
":serverKotlinJsNodeModulesTestRuntime",
":serverTest"
)
}
build("check") {
assertSuccessful()
assertTasksExecuted(
":clientKotlinJsNodeModules",
":clientKotlinJsNodeModulesTestRuntime",
":clientTest",
":serverKotlinJsNodeModules",
":serverKotlinJsNodeModulesTestRuntime",
":serverTest"
)
assertTestResults("testProject/new-mpp-js-tests/TEST-CommonTest.xml", "clientTest")
assertTestResults("testProject/new-mpp-js-tests/TEST-CommonTest.xml", "serverTest")
}
// test all is up-to-date when no changes
build("check") {
assertSuccessful()
assertTasksUpToDate(
":clientKotlinJsNodeModules",
":clientKotlinJsNodeModulesTestRuntime",
":clientTest",
":serverKotlinJsNodeModules",
":serverKotlinJsNodeModulesTestRuntime",
":serverTest"
)
}
// change common file and check that all tasks executed
projectDir.resolve("src/commonMain/kotlin/common.kt").writeText("fun common() = 777")
build("check") {
assertSuccessful()
assertTasksUpToDate(
":clientKotlinJsNodeModulesTestRuntime",
":serverKotlinJsNodeModulesTestRuntime"
)
assertTasksExecuted(
":clientKotlinJsNodeModules",
":clientTest",
":serverKotlinJsNodeModules",
":serverTest"
)
assertTestResults("testProject/new-mpp-js-tests/TEST-CommonTest-2.xml", "clientTest")
assertTestResults("testProject/new-mpp-js-tests/TEST-CommonTest-2.xml", "serverTest")
}
}
}
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<results>
<testsuite name="CommonTest" tests="3" skipped="1" failures="2" errors="0" timestamp="..." hostname="..." time="...">
<properties />
<testcase name="test1" classname="CommonTest" time="...">
<failure message="..." type="org.jetbrains.kotlin.gradle.targets.js.NodeJsTestFailure">...</failure>
</testcase>
<testcase name="test2" classname="CommonTest" time="...">
<skipped />
</testcase>
<testcase name="test3" classname="CommonTest" time="...">
<failure message="..." type="org.jetbrains.kotlin.gradle.targets.js.NodeJsTestFailure">...</failure>
</testcase>
<system-out />
<system-err />
</testsuite>
<testsuite name="InnerIgnored" tests="3" skipped="3" failures="0" errors="0" timestamp="..." hostname="..." time="...">
<properties />
<testcase name="test4" classname="InnerIgnored" time="...">
<skipped />
</testcase>
<testcase name="test5" classname="InnerIgnored" time="...">
<skipped />
</testcase>
<testcase name="test6" classname="InnerIgnored" time="...">
<skipped />
</testcase>
<system-out />
<system-err />
</testsuite>
</results>
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<results>
<testsuite name="CommonTest" tests="3" skipped="1" failures="1" errors="0" timestamp="..." hostname="..." time="...">
<properties />
<testcase name="test1" classname="CommonTest" time="..." />
<testcase name="test2" classname="CommonTest" time="...">
<skipped />
</testcase>
<testcase name="test3" classname="CommonTest" time="...">
<failure message="..." type="org.jetbrains.kotlin.gradle.targets.js.NodeJsTestFailure">...</failure>
</testcase>
<system-out />
<system-err />
</testsuite>
<testsuite name="InnerIgnored" tests="3" skipped="3" failures="0" errors="0" timestamp="..." hostname="..." time="...">
<properties />
<testcase name="test4" classname="InnerIgnored" time="...">
<skipped />
</testcase>
<testcase name="test5" classname="InnerIgnored" time="...">
<skipped />
</testcase>
<testcase name="test6" classname="InnerIgnored" time="...">
<skipped />
</testcase>
<system-out />
<system-err />
</testsuite>
</results>
@@ -0,0 +1,42 @@
import org.jetbrains.kotlin.gradle.targets.js.tasks.KotlinNodeJsTestTask
plugins {
kotlin("multiplatform").version("<pluginMarkerVersion>")
}
repositories {
mavenLocal()
mavenCentral()
jcenter()
}
kotlin {
dependencies {
commonMainImplementation(kotlin("stdlib-common"))
commonTestApi(kotlin("test-common"))
}
val jsCommon = js("jsCommon") {
dependencies {
commonMainImplementation(kotlin("stdlib-js"))
commonTestApi(kotlin("test-js"))
}
}
js("server")
js("client")
}
tasks {
"jsCommonTest"(KotlinNodeJsTestTask::class) {
ignoreFailures = true
}
"clientTest"(KotlinNodeJsTestTask::class) {
ignoreFailures = true
}
"serverTest"(KotlinNodeJsTestTask::class) {
ignoreFailures = true
}
}
@@ -0,0 +1,8 @@
pluginManagement {
repositories {
mavenLocal()
gradlePluginPortal()
}
}
rootProject.name = "new-mpp-js-tests"
@@ -0,0 +1,31 @@
package my.pack.name
import common
import kotlin.test.Ignore
import kotlin.test.Test
import kotlin.test.assertEquals
class CommonTest {
@Test
fun test1() = assertEquals(common(), 1)
@Test
@Ignore
fun test2() = assertEquals(common(), 2)
@Test
fun test3() = assertEquals(common(), 3)
@Ignore
class InnerIgnored {
@Test
fun test4() = assertEquals(common(), 1)
@Test
@Ignore
fun test5() = assertEquals(common(), 2)
@Test
fun test6() = assertEquals(common(), 3)
}
}