【问题标题】:How to make my JS tests appear in Kotlin Multiplatform project如何让我的 JS 测试出现在 Kotlin Multiplatform 项目中
【发布时间】:2018-10-03 01:11:55
【问题描述】:

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

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

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

【问题讨论】:

    标签: kotlin kotlin-multiplatform


    【解决方案1】:

    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 中创建自定义 mocha 运行/调试配置(从主菜单运行 | 编辑配置),并将其配置为类似于 runMocha gradle 任务。

    【讨论】:

    • 关于禁用 GRADLE_METADATA 以使节点插件正常工作:github.com/srs/gradle-node-plugin/issues/301
    • 这可行,但是如果还针对本机,则配置不起作用并失败,并显示“解决后无法更改配置的属性 ':app:iosApiElements'”
    【解决方案2】:

    kotlinx-io's multiplatform build configuration 的启发,在不知道自己在做什么的情况下,我设法将 JavaScript 测试配置为使用 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
    

    【讨论】:

      猜你喜欢
      • 2021-02-01
      • 1970-01-01
      • 2022-11-23
      • 2021-05-23
      • 1970-01-01
      • 2019-05-29
      • 1970-01-01
      • 2020-02-07
      • 1970-01-01
      相关资源
      最近更新 更多