如何让我的 JS 测试出现在 Kotlin Multiplatform 项目中

How to make my JS tests appear in Kotlin Multiplatform project

我正在使用 IntelliJ IDEA Multiplatform 项目,jsTest Gradle 任务未检测到任何测试。 jvmTest 测试 运行 没问题。当我 运行 带有调试输出的 jsTest 任务时,我可以看到任务 运行s 并立即完成。

Gradle 版本 4.10.1。 Kotlin 版本 1.3.0-eap.

我如何纠正 Gradle 配置,或者我可以 运行 使用什么命令,以便实际检测到测试,并且(如所写)失败?

build.gradle:

plugins {
    id 'kotlin-multiplatform' version '1.3.0-rc-131'
}
repositories {
    maven { url 'http://dl.bintray.com/kotlin/kotlin-eap' }
    mavenCentral()
}
kotlin {
    targets {
        fromPreset(presets.jvm, 'jvm')
        fromPreset(presets.js, 'js')
    }
    sourceSets {
        commonMain {
            dependencies {
                implementation 'org.jetbrains.kotlin:kotlin-stdlib-common'
            }
        }
        commonTest {
            dependencies {
                implementation 'org.jetbrains.kotlin:kotlin-test-common'
                implementation 'org.jetbrains.kotlin:kotlin-test-annotations-common'
            }
        }
        jvmMain {
            dependencies {
                implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
            }
        }
        jvmTest {
            dependencies {
                implementation 'org.jetbrains.kotlin:kotlin-test'
                implementation 'org.jetbrains.kotlin:kotlin-test-junit'
            }
        }
        jsMain {
            dependencies {
                implementation 'org.jetbrains.kotlin:kotlin-stdlib-js'
            }
        }
        jsTest {
            dependencies {
                implementation 'org.jetbrains.kotlin:kotlin-test-js'
            }
        }
    }
}

测试-project_test.js:

if (typeof kotlin === 'undefined') {
  throw new Error("Error loading module 'test-project_test'. Its dependency 'kotlin' was not found. Please, check whether 'kotlin' is loaded prior to 'test-project_test'.");
}
if (typeof this['test-project'] === 'undefined') {
  throw new Error("Error loading module 'test-project_test'. Its dependency 'test-project' was not found. Please, check whether 'test-project' is loaded prior to 'test-project_test'.");
}
if (typeof this['kotlin-test'] === 'undefined') {
  throw new Error("Error loading module 'test-project_test'. Its dependency 'kotlin-test' was not found. Please, check whether 'kotlin-test' is loaded prior to 'test-project_test'.");
}
this['test-project_test'] = function (_, Kotlin, $module$test_project, $module$kotlin_test) {
  'use strict';
  var Sample = $module$test_project.sample.Sample;
  var assertTrue = $module$kotlin_test.kotlin.test.assertTrue_ifx8ge$;
  var Kind_CLASS = Kotlin.Kind.CLASS;
  var hello = $module$test_project.sample.hello;
  var contains = Kotlin.kotlin.text.contains_li3zpu$;
  var test = $module$kotlin_test.kotlin.test.test;
  var suite = $module$kotlin_test.kotlin.test.suite;
  function SampleTests() {
  }
  SampleTests.prototype.testMe = function () {
    assertTrue((new Sample()).checkMe() > 0);
  };
  SampleTests.$metadata$ = {
    kind: Kind_CLASS,
    simpleName: 'SampleTests',
    interfaces: []
  };
  function SampleTestsJS() {
  }
  SampleTestsJS.prototype.testHello = function () {
    assertTrue(contains(hello(), 'JSSDF'));
  };
  SampleTestsJS.$metadata$ = {
    kind: Kind_CLASS,
    simpleName: 'SampleTestsJS',
    interfaces: []
  };
  var package$sample = _.sample || (_.sample = {});
  package$sample.SampleTests = SampleTests;
  package$sample.SampleTestsJS = SampleTestsJS;
  suite('sample', false, function () {
    suite('SampleTests', false, function () {
      test('testMe', false, function () {
        return (new SampleTests()).testMe();
      });
    });
    suite('SampleTestsJS', false, function () {
      test('testHello', false, function () {
        return (new SampleTestsJS()).testHello();
      });
    });
  });
  Kotlin.defineModule('test-project_test', _);
  return _;
}(typeof this['test-project_test'] === 'undefined' ? {} : this['test-project_test'], kotlin, this['test-project'], this['kotlin-test']);

Kotlin Multiplatform Tutorial

所述

At this point, test tasks for Kotlin/JS are created but do not run tests by default; they should be manually configured to run the tests with a JavaScript test framework.

您可以使用例如 mocha framework 到 运行 测试

这是我的设置:

build.gradle:

plugins {
    id 'kotlin-multiplatform' version '1.3.10' //I'm using the released version of plugin,
                                               //but it seems that they have same API
    id 'com.moowork.node' version '1.2.0' //plugin for installing node
                                          //and running node and npm tasks
}
repositories {
    mavenCentral()
}
group 'com.example'
version '0.0.1'

apply plugin: 'maven-publish'

final kotlinRuntimeVersion = '1.3.10'

final nodeVersion = '11.2.0'
final nodeWorkingDir = project.buildDir
final nodeModules = "$nodeWorkingDir/node_modules"
final mochaVersion = '5.2.0'
final pathSeparator = System.properties["path.separator"]

kotlin {
    targets {
        fromPreset(presets.jvm, 'jvm')
        fromPreset(presets.js, 'js') {
            [compileKotlinJs, compileTestKotlinJs].each { configuration ->
                configuration.kotlinOptions {
                    moduleKind = 'umd'
                }
            }
        }
    }
    sourceSets {
        commonMain {
            dependencies {
                implementation 'org.jetbrains.kotlin:kotlin-stdlib-common'
            }
        }
        commonTest {
            dependencies {
                implementation 'org.jetbrains.kotlin:kotlin-test-common'
                implementation 'org.jetbrains.kotlin:kotlin-test-annotations-common'
            }
        }
        jvmMain {
            dependencies {
                implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
            }
        }
        jvmTest {
            dependencies {
                implementation 'org.jetbrains.kotlin:kotlin-test'
                implementation 'org.jetbrains.kotlin:kotlin-test-junit'
            }
        }
        jsMain {
            dependencies {
                implementation 'org.jetbrains.kotlin:kotlin-stdlib-js'
            }
        }
        jsTest {
            dependencies {
                implementation 'org.jetbrains.kotlin:kotlin-test-js'
            }
        }
    }
}

//Workaround to copy kotlin libraries so they are visible during testing
def jsLibDir = "$compileKotlinJs.destinationDir/lib"
def jsTestLibDir = "$compileTestKotlinJs.destinationDir/lib"
configurations {
    jsLibs
    jsTestLibs
}
dependencies {
    jsLibs "org.jetbrains.kotlin:kotlin-stdlib-js:$kotlinRuntimeVersion"
    jsTestLibs "org.jetbrains.kotlin:kotlin-test-js:$kotlinRuntimeVersion"
}
task copyJsDependencies(type: Copy, dependsOn: compileKotlinJs) {
    configurations.jsLibs.each {
        from zipTree(it.absolutePath).matching { include '*.js'}
    }
    into jsLibDir
}
jsMainClasses.dependsOn copyJsDependencies
task copyJsTestDependencies(type: Copy) {
    configurations.jsTestLibs.each {
        from zipTree(it.absolutePath).matching { include '*.js'}
    }
    into jsTestLibDir
}
jsTestClasses.dependsOn copyJsTestDependencies

//Use mocha to run js tests
node {
    version = nodeVersion
    download = true
    workDir = file("$project.buildDir/nodejs")
    nodeModulesDir = file(nodeWorkingDir)
}
task installMocha(type: NpmTask, group: 'npm') {
    outputs.dir "$nodeModules/mocha"
    args = ['install', "mocha@$mochaVersion"]
}
task runMocha(type: NodeTask, dependsOn: [installMocha, jsMainClasses, jsTestClasses], group: 'npm') {
    environment = [ "NODE_PATH": "$jsLibDir$pathSeparator$jsTestLibDir$pathSeparator$compileKotlinJs.destinationDir" ]
    script = file("$nodeWorkingDir/node_modules/mocha/bin/mocha")
    args = [compileTestKotlinJs.outputFile]
}
jsTest.dependsOn runMocha

settings.gradle:

pluginManagement {
    resolutionStrategy {
        eachPlugin {
            if (requested.id.id == "kotlin-multiplatform") {
                useModule("org.jetbrains.kotlin:kotlin-gradle-plugin:${requested.version}")
            }
        }
    }
}
rootProject.name = 'test'

出于某些原因,禁用 gradle 中的元数据功能对于节点插件正常工作很重要。

通过此设置,您将 运行 jsTest gradle 任务的 js 测试(这对于 CI 很重要)但它们不会出现在想法中 window 就像他们对 java 测试所做的那样,你仍然无法调试它们。

要在 IntelliJ IDEA 中执行此操作,您可以创建自定义 mocha run/debug 配置(运行 | 从主菜单编辑配置),并类似于 runMocha gradle任务。

受到 kotlinx-io's multiplatform build configuration 的启发,在不知道自己在做什么的情况下,我设法使用 Mocha 将 JavaScript 测试配置为 运行。

compileKotlinJs.configure {
    kotlinOptions {
        metaInfo = true
        sourceMap = true
        moduleKind = 'umd'
        main = "noCall"
        sourceMapEmbedSources = 'always'
    }
}

compileTestKotlinJs.configure {
    kotlinOptions {
        metaInfo = true
        sourceMap = true
        moduleKind = 'umd'
        main = "call"
        sourceMapEmbedSources = 'always'
    }
}

task copyJsDependencies(type: Copy, dependsOn: compileTestKotlinJs) {
    from compileKotlinJs.destinationDir
    into "${buildDir}/node_modules"

    def configuration = configurations.jsTestRuntimeClasspath
    from(files {
        configuration.collect { File file ->
            file.name.endsWith(".jar")
                ? zipTree(file.absolutePath).matching {
                    include '*.js'
                    include '*.js.map' }
                : files()
        }
    }.builtBy(configuration))
}

node {
    version = nodeVersion
    download = true
}

task installMocha(type: NpmTask) {
    args = ['install', 'mocha']
}

task runMocha(type: NodeTask, dependsOn: [installMocha, compileTestKotlinJs, copyJsDependencies]) {
    script = file('node_modules/mocha/bin/mocha')
    args = [compileTestKotlinJs.outputFile]
}

jsTest.dependsOn runMocha