New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support for nested tests on JS target (again) #3141
Comments
The Javascript test runners don't support promises at the outer layer. Eg in mocha,
Therefore we cannot use coroutines anywhere but the final scope. Since kotest supports coroutines at every layer, the only way to make it work in JS land is to support flat tests only. Unless you can find a JS test runner that supports promises at every level of nesting. The alternative would be to change kotest to not support coroutines anywhere but the final scope, and that would be a) a huge breaking change and b) reduce the functionality for anyone in JVM land. |
It looks like https://github.com/substack/tape might supported nested async tests, so we could explore that for Kotest 6.0 |
@sksamuel I can't find anything in Tape's documentation about nested async tests (that also have the top levels async). Would you mind pointing something to me? I am not against trying to make an implementation. Also, I understand that it would indeed be a huge breaking change. However, I am not sure to understand the interest of having the top levels being async too. |
Aside from whether it's a good idea or not to have async parent tests, changing it now would break thousands of installs. In tape it looks like a top level |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
Very much a hack, but I got this working which suits my needs, and should be easy to migrate over if/when nested JS test support is added: FlatSpec.kt Obligatory disclaimer: use with caution. No guarantee it'll work in future releases, as using |
* bump Gradle 7.5.1 * create KxsTsGenBuildSettings, so TSCompile tests can be enabled/disabled with a flag * create github workflows * kotlin.mpp.stability.nowarn=true * bump kotlinx-kover * bump kotlin 1.7.21 * bump gradle-git-versioning-plugin * tweak gradle props * update property name kxstsgen_enableTsCompileTests * increase logging, disable fail-fast * binaries.executable() -> browser() * add rootProject.name to buildSrc Gradle settings * bump Kotlin language level to 1.7, standardise Jvm target to 11 * rm java-library from kotlin-mpp * setup java-test-fixtures, change 'example' to be in 'main' source set * only enable NPM setup when TSCompile is enabled * update kotlin-process * disable kotest plugin kotest/kotest#3141 * use embeddedKotlinVersion shortcut * improve ts compile testing * combine TS compile tests in matrix
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
Maybe using kotlin.test could help with dynamic test registration on JS? https://discuss.kotlinlang.org/t/kotlin-test-js-specifying-test-without-annotation/11280
I've fleshed this out and created a working example on Kotlin 1.8.10, JS IR browser import kotlin.test.Test
import kotlin.test.assertTrue
@JsModule("kotlin-test")
@JsNonModule
external val kTest: dynamic
class TestJs {
// some dummy service that we'll test
class UsernameValidator {
fun isValid(username: String?) = username!!.isNotBlank()
}
@Test
fun passwordValidationTests() {
// create an outer context
context("Given a password validator") {
val usernameValidator = UsernameValidator()
// nest some inner contexts + tests
context("When username is very long") {
val username = "very long username ".repeat(100)
test("Then expect validation passes") {
assertTrue { usernameValidator.isValid(username) }
}
}
context("When username is not blank") {
val username = "foo bar"
test("Then expect validation passes") {
assertTrue { usernameValidator.isValid(username) }
}
}
// tests + contexts can be dynamically added
mapOf(
"blank" to " ",
"null" to null,
).forEach { (failureReason, username) ->
context("When username is $failureReason") {
test("Then expect validation fails") {
assertTrue { usernameValidator.isValid(username) }
}
}
}
}
}
}
/** Test context - for nesting tests */
fun context(name: String, ignored: Boolean = false, contextBlock: () -> Unit) {
kTest.kotlin.test.suite(name, ignored) {
contextBlock()
}
}
/** Execute a test */
fun test(name: String, ignored: Boolean = false, testBlock: () -> Unit) {
kTest.kotlin.test.test(name, ignored) {
testBlock()
}
} Example result: So the tests aren't nested, but kotlin.test will prepend the contexts to the test name. |
Is there any plan to support this anytime soon? I'm porting a JVM library to KMP and running into this issue when adding a js target. I'd hate to move away from kotest and there are hundreds of tests that are affected. |
It's going to be added when we can build on top of compiler plugins stably. I am hoping that will be after Kotlin 2.0 is released. |
Nested tests on JS target were working in 5.0.0. However, it seems to be broken in newer versions.
One of the good things of Kotest is the ability to have nested tests. However, nested tests not working on the JS target means that you're stuck to not using this feature as soon as you have a multiplatform Kotlin project that also targets JS (which is supposed to be a lot of projects). This is a feature that is tremendously useful to organize tests in big projects.
I have seen here that @sksamuel says:
However, nested tests are supported in (almost) all test runners in the JS world. So it would seem that the problem comes from Kotest design.
In addition, in some Slack discussion that I can't find again, @sksamuel said that the problem comes from intermediate (container) levels use suspending lambda. I am wondering why this is, as from my point of view, suspending lambdas only make sense for the content of individual tests and before/after hooks.
I also have seen that there is a work-in-progress PR on this subject.
@sksamuel could we please discuss what needs to (breaking) change in Kotest to support this?
The text was updated successfully, but these errors were encountered: