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

时间:2018-10-03 01:11:56

标签: kotlin kotlin-multiplatform

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

版本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'
            }
        }
    }
}

test-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']);

2 个答案:

答案 0 :(得分:2)

Kotlin Multiplatform Tutorial

所述
  

这时,创建了Kotlin / JS的测试任务,但默认情况下不运行测试;应该手动配置它们以使用JavaScript测试框架运行测试。

例如,您可以使用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来说很重要),但是它们不会像在Java测试中那样出现在提示窗口中将无法对其进行调试。

要在IntelliJ IDEA中执行此操作,您可以创建自定义的摩卡运行/调试配置(从主菜单运行|编辑配置),并与runMocha gradle任务类似地进行配置。

答案 1 :(得分:0)

Inspired by kotlinx-io's multiplatform build configuration, without really knowing what I am doing, I managed to configure JavaScript tests to run using Mocha.

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