Why is kotest better than JUnit/Spock/whatever? Wh...
# kotest
a
Why is kotest better than JUnit/Spock/whatever? What killer features convinced you to make the switch? How would you convince someone to move over to kotest? I'm trying to convince a few folks, and I'd appreciate your help.
l
• Coroutines ready • Assertions far superior than anything I've ever seen in any testing framework.
shouldBe
is delicious to use • Testing styles that allow for nesting and more complex per-test configuration • Plain Kotlin code -- Fits with everything that's Kotlin related without loops and hoops
1
And more. As a short pitch for me, Kotest is to Junit what Kotlin is to Java
1
a
TY! Arbs and shrinking are cool too. But are there good examples of "coroutines ready" - I've tried that but it did not work well.
"Kotest is to Junit what Kotlin is to Java" - that's a great title for a presentation
l
But are there good examples of "coroutines ready" - I've tried that but it did not work well.
Call a suspend function in JUnit. Now call it it Kotest. Kotest just runs it, JUnit needs
runBlocking
or
runBlockingTest
and then your test is blocking and no longer coroutines
👍 1
a
• powerful json matchers
l
If you test coroutines it's always blocking anyway
BTW in JUnit
runTest
should be used
Coroutines support is not always intuitive in Kotest, e.g. nested tests don't inherit
testScheduler
from parents: https://github.com/kotest/kotest/issues/3705
👍 1
o
I'd say Kotest is just way more powerful out of the box: • Multiplatform – just like Kotlin. • Dynamic/configurable tests in plain Kotlin:
Copy code
for (animal in listOf("cat", dog", "bird")) {
    test("feeding $animal") {
        ...
    }
}
• Context information for failing tests via
withClue()
. • Non-deterministic testing (
eventually()
, ...)
gratitude thank you 1
a
what are the real life scenarios where
eventually()
is used?
o
I even use custom variants of eventually for that:
Copy code
eventuallyTimestamped(5.seconds, "Waiting for the frontend's service startup") {
            compositionIsReady() shouldBe true
            frontend.context.service shouldNotBe null
        }
gratitude thank you 1
a
Congrats! Provoking collisions is very interesting. We've recently tested a system that allocates resources, similar to selling tickets - it was very good learning, and nice use of CircularBreaker
o
Yeah, the good thing on E2E integration testing is that you don't always have to anticipate what could possibly go wrong. The tests will find stuff you never thought about.
a
this
but once the failing components have been found, it's nice to stress test them in isolation, and keep those tests, to make sure they stay fixed
o
Yes, that doesn't hurt. But with unit tests, we're testing for the failure modes we know. It's always good to have some techniques to help find the other ones. For example, with concurrent algorithms, Kotlin's Lincheck library does that.
gratitude thank you 1
a
many of our race conditions involve Postgres, and IMO lincheck won't help in that, unless I'm missing something
o
No, that's correct. Lincheck is for in-process concurrency, and in that habitat, it does a remarkable job. And for cross-process concurrency, one option is E2E testing, which you can make more focused via Kotest's non-deterministic functions, plus some other techniques I'll be covering in that talk.
🎉 1
👍 1