Update While searching for the optimal solution, I switched temporarily to an approach using a dedicated test factory that performs the init in combination with forAll
. In this way, I don't have to repeat the init code in every test factory.
fun somePreStuffFactory() = funSpec {
beforeTest {
println("Do some init stuff here")
}
test("dummy test just to trigger beforeTest") {}
}
class MyTest : FunSpec({
runBlocking {
forAll(
row(MyTestFactory::someTest1),
row(MyTestFactory::someTest2)
) { testFactoryFunc ->
include(somePreStuffFactory())
include(testFactoryFunc())
}
}
})
End of update
I have a lot of tests inside test factories. Before running the tests inside a test factory, I need to do some initial setup in the beginning of each test factory, and the setup is the same for all test factories.
Problem is that beforeSpec
is not invoked inside test factory, hence I'm currently using a dirty workaround by doing init stuff in the first test in each test factory. I would highly appreciate any advice on this.
The optimal solution would be to have a life-cycle hook inside the the test class that runs before each test factory.
Code to reproduce
class MyTest : FunSpec({
include(someTest1())
include(someTest2())
})
import io.kotest.core.spec.style.funSpec
object MyTestFactory {
fun someTest1() = funSpec {
beforeSpec {
/** Not invoked */
println("Hello from someTest1#beforeSpec")
}
test("Init stuff is done inside a test") {
/** some init here */
}
test("first test") {
println("Hello from first test")
}
test("second test") {
println("Hello from second test")
}
}
fun someTest2() = funSpec {
beforeSpec {
/** Not invoked */
println("Hello from someTest2#beforeSpec")
}
test("Init stuff is done inside a test") {
/** some init here */
}
test("third test") {
println("Hello from third test")
}
}
}
What I've tried so far
After bumping Kotest from 4.6.4 to 5.4.2, I was able to run the code in answer from @ocos. Problem is that BeforeSpecSample#beforeSpec is invoked just once, not for each test factory which is my requirement.
object BeforeSpecSample : BeforeSpecListener {
override suspend fun beforeSpec(spec: Spec) {
println("Hello from beforeSpec")
}
}
class MyTest : FunSpec({
extensions(BeforeSpecSample)
include(someTest1())
include(someTest2())
})
Update
After reading this GitHub issue, I successfully tested the following approach using a boolean var initialized
andbeforeTest
. It would have been nice if this approach could be used inside test class instead of inside each test factory, but without any life-cycle hooks for test factories, I don't see how that can be done.
fun someTest1() = funSpec {
var initialized = false
beforeTest {
if (!initialized) {
println("Hello from someTest1#beforeTest")
initialized = true
}
}
/** tests goes here */
}
Environment Kotest 4.6.4, Kotlin 1.7.10, Micronaut 3.6.3