2

I've started using kotest:4.0.5 (kotlintest) and having problem with stringSpec function nested in describe clause.

Example:

class SellerTest : DescribeSpec({

    describe("Registration") {
        context("Not existing user") {
            include(emailValidation()
        }
    }
})

fun emailValidation() = stringSpec {
    "Email validation" {
        forAll(
            row("test.com"),
            row("123123123123123")
        ) { email ->
            assertSoftly {
                val exception =
                    shouldThrow<ServiceException> { Email(email) }

            }
        }
    }
}

If include(emailValidation()) is outside describe clause then correctly works.

Have you any idea how to nest specs/functions in clauses?

MrNetroful
  • 497
  • 8
  • 28

2 Answers2

2

You can only use include at the top level. This is part of how factory tests (what the include keyword is used for) are implemented (perhaps that will be relaxed in a future release).

You can move the whole thing into the factory though.

class SellerTest : DescribeSpec({
  include(emailValidation)
})

val emailValidation = describeSpec {

    describe("Registration") {
        context("Not existing user") {
            forAll(
                row("test.com"),
                row("123123123123123")
            ) { email ->
                assertSoftly {
                    val exception =
                        shouldThrow<ServiceException> { Email(email) }
                }
            }
        }
    }
}

And you can parameterize the naming all you want, as that's just strings, for example:

fun emailValidation(name: String) = describeSpec {
    describe("Registration") {
        context("$name") {
        }
    }
}

If you are not parameterizing, then there's little point in having the test factory. Just declare the test inline IMO.

sksamuel
  • 16,154
  • 8
  • 60
  • 108
  • Thanks, Honestly its not what I dreamed about ^^. I thought someone will have magic solution. Hopefully it will change in future. – MrNetroful May 27 '20 at 21:09
  • What are you trying to achieve vs what I showed. Maybe there's some other way of getting the same result. – sksamuel May 27 '20 at 23:39
  • Email validation is part of registration process so it cannot be like that. I wanted to nest it in registration describe. But if its not possible then probably will include it out of scope. – MrNetroful May 28 '20 at 07:22
1

For nested include you may implement your own factory method like this example:

class FactorySpec : FreeSpec() {
    init {
        "Scenario: root container" - {
            containerTemplate()
        }
    }
}

/** Add [TestType.Container] by scope function extension */
suspend inline fun FreeScope.containerTemplate(): Unit {
    "template container with FreeScope context" - {
        testCaseTemplate()
    }
}

/** Add [TestType.Test] by scope function extension */
suspend inline fun FreeScope.testCaseTemplate(): Unit {
    "nested template testcase with FreeScope context" { }
}

Pay attention to the Scope that is passed to the extension function for containerTemplate and testCaseTemplate

Output:

Scenario: root container
   template container with FreeScope context
       nested template testcase with FreeScope context