https://kotlinlang.org logo
#multiplatform
Title
# multiplatform
n

natpryce

02/18/2019, 3:55 PM
Wow. Getting tests to run for a JS target in a multiplatform project is difficult: it’s not documented, and there are no examples in the kotlin-examples repo, and Gradle is opaque even with a Kotlin build script. Anyone got a small example of a multiplatform project that runs the tests for both the JVM and JS platforms?
💯 2
i

ian.shaun.thomas

02/18/2019, 4:00 PM
n

natpryce

02/18/2019, 4:02 PM
Thanks. That’s not exactly a small example, though. What am I meant to look at in there?
There are lots of dependencies and plugins added to that project.
i

ian.shaun.thomas

02/18/2019, 4:03 PM
it's pretty small as far as practical examples ago. look at the usage of
id 'com.github.salomonbrys.gradle.kotlin.js.mpp-tests.node'
in the plugins and then the JS configuration block in the targets
Copy code
fromPreset(presets.js, 'js') {
            tasks[compilations.main.compileKotlinTaskName].kotlinOptions.moduleKind = "umd"
            kotlinJsNodeTests {
                thisTarget(js) {
                    engine = mocha
                }
            }
            mavenPublication {
                artifactId = 'arbor-js'
            }
        }
n

natpryce

02/18/2019, 4:03 PM
Do you know of a minimal example project? E.g. just using kotlin-multiplatform plugin?
i

ian.shaun.thomas

02/18/2019, 4:04 PM
that's not really possible
n

natpryce

02/18/2019, 4:05 PM
Why?
i

ian.shaun.thomas

02/18/2019, 4:05 PM
you can't run tests without an environment to run tests in and kotlin is unopinionated about platform targets
in this project I'm using node to run the tests
n

natpryce

02/18/2019, 4:05 PM
Obvs…
to run the tests for the JVM, I use the JVM. To run the tests for JS I use Node. That’s not a problem.
i

ian.shaun.thomas

02/18/2019, 4:06 PM
right, that's the example of how to do it then unless you want to manually write all the tasks to do things like grab node, set it up, copy the tests, run the node tasks, process the unit tests, etc
kotlin mpp does not provide any facilities for testing js
n

natpryce

02/18/2019, 4:09 PM
Is the stuff that com.github.salomonbrys.gradle.kotlin.js.mpp-tests.node does going to be supported by kotlin-multiplatform?
i

ian.shaun.thomas

02/18/2019, 4:09 PM
no, much like they don't support running android test or ios tests. They may suggest how to do it but that's not inside the scope of mpp itself
jvm only works because the kotlin plugin already wires that up so mpp gets it for free
for instance, how do you run tests for wasm or arm generated code? They are unopinionated about those as well.
n

natpryce

02/18/2019, 4:13 PM
I don’t care about it’s opinion. I’d be happy it provided convenient defaults, and the ability to target different configuraitons — just like it does with the JVM. By default it runs on JUnit, but I can configure the test framework, the JVM version it uses, etc.
i

ian.shaun.thomas

02/18/2019, 4:14 PM
yes because kotlin (jvm) has an opinion on testing, mpp does not
n

natpryce

02/18/2019, 4:15 PM
But the Kotlin JS compiler does have an opinion on testing. More so than the Kotlin JVM compiler, because test code is targetted to the test framework by the compiler
“main” and “test” modules generate quite different JS
i

ian.shaun.thomas

02/18/2019, 4:17 PM
kotlin examples are the same thing im showing you https://github.com/JetBrains/kotlin-examples/blob/master/gradle/js-tests/qunit/build.gradle that is use the gradle node plugin which
com.github.salomonbrys.gradle.kotlin.js.mpp-tests.node
builds upon (it uses that same plugin)
kotlin js is not opinionated about testing they just have an example showing how you could do it
n

natpryce

02/18/2019, 4:17 PM
Yeah. I’m using the gradle node plugin.
i

ian.shaun.thomas

02/18/2019, 4:18 PM
right, that's not jetbrains though
n

natpryce

02/18/2019, 4:19 PM
Sure. But it’s more active and has more developers than the mpp-tests.node plugin. The worry is, when mpp evolves, will mpp-tests.node keep up? It’s a hard sell.
i

ian.shaun.thomas

02/18/2019, 4:20 PM
More so than the Kotlin JVM compiler, because test code is targetted to the test framework by the compiler
that's not the case, you define amd/umd/js but qunit and others are what you are passing to the node plugin
all that plugin does is copy the files for you and place them into the correct spots. You don't have to use it. Much like all the node plugin does is provide some convenience but it doesn't really do anything magical other than give some easy configuration.
n

natpryce

02/18/2019, 4:22 PM
I mean… if I compile a Kotlin module, it gets compiled to plain ol’ JS functions if it’s a main module, and to test code if it’s a test module.
The output is quite different.
“all that plugin does is copy the files for you and place them into the correct spots. You don’t have to use it.” <-- Agreed. That’s what I’m looking for examples of.
i

ian.shaun.thomas

02/18/2019, 4:25 PM
Read the plugin code then, it breaks down to basically 3 gradle tasks. Copying the files, configuration of node, running the tests. Basically the same thing as that kotlin js project I linked but modified for the requirements of the mpp task graph and outputs.
g

gildor

02/19/2019, 12:28 AM
This is example without additional plugins (except node, also see root build.gradle, there are test dependencies for js): https://github.com/gildor/knel/blob/master/js-test.gradle
It based on some example from @Deactivated User, but I couldn't find original repo Also, I would say that I agree, that It would be great to have support of popular test frameworks for JS out of the box (or even only 1 particular) with browser and node targets to run tests. Because now it's quite cumbersome to configure
i

ian.shaun.thomas

02/19/2019, 1:09 AM
I would like to see official support but outside of the MPP plugin. As an Android dev I'm extremely weary of "do everything" plugins.
g

gildor

02/19/2019, 1:54 AM
But how do you want do this without plugin?
Plugin is just a way to extend features of Gradle, this is whole point of Gradle and any other build tool
i

ian.shaun.thomas

02/19/2019, 1:55 AM
As separate plugins as it is now
g

gildor

02/19/2019, 1:56 AM
Yes, it can be additional plugin, one per each test framework, I agree
But this plugin still should have some integreation with MPP or/and with kotlin.platform.js plugin
i

ian.shaun.thomas

02/19/2019, 2:17 AM
Sure and we have that right now
It's not jetbrains but it works fine short of code coverage
n

natpryce

02/19/2019, 8:48 AM
@gildor Thanks — that’s exactly what I’m looking for.
A quick question: why does the build file use
kotlin.targets.fromPreset(presets.jvm, "jvm")
etc. instead of
jvm("jvm")
, etc.?
The documentation shows the latter syntax, but I’ve seen a number of projects on GitHub that use the former syntax. Is there a reason why?
g

gildor

02/19/2019, 8:52 AM
The later is new DSL, from 1.3.20 I believe
n

natpryce

02/19/2019, 8:52 AM
That explains it. Thanks again.
g

gildor

02/19/2019, 8:53 AM
New MPP is under active development, so a lot of things could changed
n

natpryce

02/19/2019, 9:05 AM
Yes. Unfortunately your js test tasks don’t work in 1.3.21. I’m back to the same error that made me start this thread.
That’s the risk of being on the bleeding edge 😄
g

gildor

02/19/2019, 9:31 AM
what kind error do you have?
n

natpryce

02/19/2019, 10:28 AM
Copy code
A problem occurred evaluating script.
> Cannot access first() element from an empty Iterable
From the argument passed to Mocha:
relativePath("${jsCompilations.test.output.classesDirs.first()}/${project.name}_test.js")
I’ll clone your project and see if it builds when I upgrade the kotlin mpp version
g

gildor

02/19/2019, 10:29 AM
Yeah, something changed in task output
n

natpryce

02/19/2019, 10:29 AM
The error could well be caused by other funky stuff in my build
I’ve got it running the tests (and failing where behaviour differs from the JVM, which is great). Thanks for your help
I had to change the argument to Mocha to be
relativePath(jsCompilations.test.output.allOutputs.first()) + "/${project.name}_test.js"
And found that I’d not specified the module type for generated JS modules. I assumed it would default to UMD, and that UMD would be compatible with CommonJS, but unless I specified “umd” for the main JS module and “commonjs” for the test JS module, Mocha would not find the kotlin stdlib when running the tests.
No idea why. It’s just magic to me at this point.
g

gildor

02/19/2019, 2:05 PM
By default there is no module system, so it make sense
n

natpryce

02/19/2019, 2:57 PM
Ah. That does make sense.
Thanks all. I now have a passing build on both JVM and JS platforms. https://travis-ci.org/npryce/hamkrest/builds/495569560
👍 1