Hi All! I seem to have an issue running tests. I ...
# javascript
s
Hi All! I seem to have an issue running tests. I have a simple test like the following
Copy code
//COMMON CODE
class CredentialsManagerTest: BaseTest() {

    @Test
    fun runTest() = runTest {
        fail()
    }

}

expect abstract class BaseTest(){
    fun <T> runTest(block: suspend CoroutineScope.() -> T)
}

//JS ACTUAL
actual abstract class BaseTest actual constructor() {
    actual fun <T> runTest(block: suspend CoroutineScope.() -> T) {
    }
}
The test runs in JS
Copy code
> Task :common:compileKotlinJs UP-TO-DATE
> Task :common:jsMainClasses UP-TO-DATE
> Task :common:compileTestKotlinJs UP-TO-DATE
> Task :common:compileDevelopmentTestKotlinJs UP-TO-DATE
> Task :common:jsTestClasses UP-TO-DATE
> Task :common:jsBrowserTest
Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See <https://docs.gradle.org/6.3/userguide/command_line_interface.html#sec:command_line_warnings>
BUILD SUCCESSFUL in 14s
I have it setup to use Firefox as the test browser
Copy code
browser() {
    webpackTask() {
        mode = org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig.Mode.DEVELOPMENT
        sourceMaps = true
    }
    testTask {
        useKarma { useFirefox() }
        enabled = true
    }
}
But the test passes?? It runs the test in the browser and goes green. I cant seem to make it fail? Am I missing something? This is in a Multiplatform Project and has an Android Component also.
1
Gradle File:
Copy code
plugins {
    id("com.android.library")
    kotlin("multiplatform")
    kotlin("plugin.serialization")
    id("kotlin-dce-js")
    id("maven-publish")
}

kotlin {

    android()

    js {
        targets {
            produceExecutable()
            browser() {
                webpackTask() {
                    mode = org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig.Mode.DEVELOPMENT
                    sourceMaps = true
                }
                testTask {
                    useKarma { useFirefox() }
                    enabled = true
                }
            }
            compilations.all {
                kotlinOptions {
                    freeCompilerArgs = freeCompilerArgs + "-Xopt-in=kotlin.RequiresOptIn"
                    freeCompilerArgs = freeCompilerArgs + "-Xopt-in=kotlin.js.ExperimentalJsExport"
                }
            }
        }
    }

    sourceSets {
        all {
            languageSettings.apply {
                useExperimentalAnnotation("kotlinx.coroutines.ExperimentalCoroutinesApi")
            }
        }
    }

    sourceSets["commonMain"].dependencies {
        implementation(Coroutines.common)
        implementation(Ktor.commonSerializationRuntime)
        implementation(Ktor.commonCore)
        implementation(Ktor.commonSerialization)
        implementation(Kotlin.standardLibCommon)
    }

    sourceSets["commonTest"].dependencies {
        implementation(KotlinTest.common)
        implementation(KotlinTest.annotations)
        implementation(KotlinTest.mockk)
    }

    sourceSets["jsMain"].dependencies {
        implementation(Kotlin.standardLibJS)
        implementation(Ktor.js)
        implementation(Ktor.jsSerialization)
        implementation(Ktor.jsJson)
        implementation(Coroutines.js)
        implementation(Ktor.jsSerializationRuntime)
        implementation(npm("text-encoding"))
        implementation(npm("abort-controller"))
        implementation(npm("utf-8-validate"))
        implementation(npm("bufferutil"))
        implementation(npm("fs"))
    }

    sourceSets["jsTest"].dependencies {
        implementation(KotlinTest.js)
    }

    sourceSets["androidMain"].dependencies {
        implementation(kotlin("stdlib", Versions.kotlin))
        implementation(Coroutines.android)
        implementation(Ktor.androidSerializationRuntime)
        implementation(Ktor.androidCore)
        implementation(Ktor.androidSerialization)
        implementation(Kotlin.standardLibJDK8)
        implementation("androidx.core:core-ktx:1.2.0")
    }

    sourceSets["androidTest"].dependencies {
        implementation(KotlinTest.jvm)
        implementation(KotlinTest.junit)
        implementation(AndroidXTest.core)
        implementation(AndroidXTest.junit)
        implementation(AndroidXTest.runner)
        implementation(AndroidXTest.rules)
        implementation(Coroutines.test)
    }

}

android {
    compileSdkVersion(App.compileSdk)

    defaultConfig {
        minSdkVersion(App.minSdk)
        targetSdkVersion(App.targetSdk)
        versionCode = App.versionCode
        versionName = App.versionName
        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
    }

    packagingOptions {
        exclude("META-INF/*.kotlin_module")
    }

    sourceSets {
        getByName("main") {
            manifest.srcFile("src/androidMain/AndroidManifest.xml")
            java.srcDirs("src/androidMain/kotlin")
            res.srcDirs("src/androidMain/res")
        }
    }

    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
}
i
Could you see in
build/reports/tests/…
index.html
It should report what tests was run, and what succeed and failed
s
testResult.png
Currently I only have 1 test. But this is what happens. The test is ment to just "fail" but passes each time
i
Copy code
//JS ACTUAL
actual abstract class BaseTest actual constructor() {
    actual fun <T> runTest(block: suspend CoroutineScope.() -> T) {
    }
}
Is it real code? You don’t call anything in body, is it expected? At least, generation of this file and reporting of 1 passed test means that, configuration is valid. Maybe some other problems possible
s
I used the same sample of running tests that they currently use in https://github.com/touchlab/KaMPKit
Wait... Im missing something with that to invoke the block I think.
I just tried with the following.
Copy code
actual fun <T> runTest(block: suspend CoroutineScope.() -> T) {
        GlobalScope.launch { block() }
    }
Get the same issue
Ok, going to scrap this approach. Im just going to deal with Coroutines as a problem when it becomes a problem. Ill run them raw for now 🙂 Thank you @Ilya Goncharov [JB]
i
So, if you have reproducer I can take a look And @bashor or @anton.bannykh could you take a look? Maybe you know some problems with testing suspend functions?
s
I removed all the Coroutine test runner code and kept it clean for now. I dont think its needed immediatly 🙂
r
Your
GlobalScope.launch
isn't working because nothing is joining/awaiting so the test function returns before the block has been run. This youtrack ticket has a recipe for testing suspend functions in JS via promises: https://youtrack.jetbrains.com/issue/KT-22228
👍 1
s
I followed the example with the promise and that has worked! Thank you again @russhwolf and @Ilya Goncharov [JB]