https://kotlinlang.org logo
#kotest
Title
# kotest
o

Oliver.O

01/16/2023, 12:08 PM
I'm trying to decipher how
AbstractProjectConfig
works in Kotlin/Js (in a standard multiplatform configuration using Karma). My preliminary findings suggest that a
BeforeProjectListener
extension works as expected while a `ProjectExtension`'s
interceptProject
method is not being invoked. Are there any known limitations? Also, what are the entry points into the Kotest framework on Js?
1
s

sam

01/16/2023, 1:24 PM
Any subclass of AbstractProjectConfig should be picked up by the JS compiler plugin and then activated before the tests begin.
Try registering the ProjectExtension inside the config.
o

Oliver.O

01/16/2023, 1:35 PM
I have this one in `commonTest`:
Copy code
open class CommonTestConfiguration(
    private val loggingConfiguration: LoggingConfiguration = LoggingConfiguration(::emitViaPrintln)
) : AbstractProjectConfig() {

    override fun extensions() =
        listOf(
            LoggingTestProjectExtension(loggingConfiguration),
            DebugTraceTestProjectExtension
        )

    private class LoggingTestProjectExtension(val loggingConfiguration: LoggingConfiguration) : BeforeProjectListener {
        override suspend fun beforeProject() {
            loggingConfiguration.activate()
            <http://logger.info|logger.info> { "testVariant: $testVariant" }
        }
    }

    private object DebugTraceTestProjectExtension : ProjectExtension, SpecExtension, TestCaseExtension {
        override suspend fun interceptProject(context: ProjectContext, callback: suspend (ProjectContext) -> Unit) {
            DebugTrace.enabled = true // <- the effect of this one seems to be missed

            callback(context)
        }

        override suspend fun intercept(spec: Spec, execute: suspend (Spec) -> Unit) {
            execute(spec) // plus other stuff
        }

        override suspend fun intercept(testCase: TestCase, execute: suspend (TestCase) -> TestResult): TestResult =
            execute(testCase) // plus other stuff
    }
}
And this in a Js source set:
Copy code
object TestConfiguration : CommonTestConfiguration(LoggingConfiguration(::emitViaPrintln))
On the Jvm, everything works as expected. On Js, it seems like an invocation of
interceptProject
is missing. Regarding the others, I don't know yet. Still investigating. But thanks for the plugin hint.
s

sam

01/16/2023, 1:37 PM
interceptProject should work as it's just inside the shared engine code.
the difference between JS and JVM is that on JS the specs are never instantiated, they are always pre-instantiated
So that might be why you don't see intercept(spec)
o

Oliver.O

01/16/2023, 1:41 PM
I'll try to find out more. Seems a bit hard to debug those pieces (but this may be due to my specific configuration), and console output seems to be unavailable either at this stage.
s

sam

01/16/2023, 1:42 PM
project config's have an after/before project method directly in them you can override too.
o

Oliver.O

01/16/2023, 2:06 PM
Could make the debugger work.
interceptProject
gets invoked. Actually, it seems to be invoked twice (but that's not an issue at this time). So the root cause of my issue (a global flag in a companion object having an unexpected value) might be unrelated to Kotest. Thanks so much for bearing with me!
s

sam

01/16/2023, 2:07 PM
Glad you were able to make progress.
o

Oliver.O

01/16/2023, 4:10 PM
Seems like the root cause was a lifecycle discrepancy between JVM and Js. My original code looked like this (yes, shortening it above to conserve reading bandwith was the wrong idea in this case):
Copy code
override suspend fun interceptProject(context: ProjectContext, callback: suspend (ProjectContext) -> Unit) {
            val debugTraceEnabledBefore = DebugTrace.enabled
            DebugTrace.enabled = true

            callback(context)

            DebugTrace.enabled = debugTraceEnabledBefore
        }
On the JVM, the intercept's callback returns after all tests have completed. On Js, it returns before any test had a chance to run. The same applies to `AbstractProjectConfig`'s
afterProject
method. So on Js, the
enabled
setting got reset before a single test would run. Maybe it would be a good idea to harmonize lifecycle methods between different platforms, if feasible. Or at least document the exact order of invocations.
s

sam

01/16/2023, 4:12 PM
That sounds like a bug to me.
o

Oliver.O

01/16/2023, 4:12 PM
OK, in this case I'll prepare an issue along with a reproducer.
s

sam

01/16/2023, 4:13 PM
intercept project should have the same behavior across all platforms
s

sam

01/16/2023, 10:22 PM
Thanks for making the issue. Definitely a bug on JS that the spec/project exit occurs before any tests are executed.
39 Views