kotlinkotest

Can you specify enabled condition for all test in spec in Kotest 5?


Before Kotest 5.0, you could apply a default test config to set some properties, like if the tests are enabled or what the timeout is.

Kotest 4

class DbTests : StringSpec() {
    override val defaultTestCaseConfig: TestCaseConfig = TestCaseConfig(enabled = !IS_CI, timeout = 24.hours)

    init {
        "test1" { ... }
        "test2" { ... }
    }
}

However, since Kotest 5, the defaultTestCaseConfig syntax has been deprecated https://kotest.io/docs/blog/release_5.0/#default-test-case-config (thankfully, just as a warning for now) with DSL-like syntax in the init block replacing it. But that syntax seems to lack the enabled field, which I was using to switch all test in a spec on/off at the same time. I can still apply the condition on a test-by-test basis, but that is duplicate code and what if you forget one?

Kotest 5

class DbTests : StringSpec() {
    override fun defaultTestCaseConfig(): TestCaseConfig = TestCaseConfig(enabled = !IS_CI, timeout = 24.hours) // deprecated

    init {
        timeout = 24.hours
        //enabled - no field to add

        "test1".config(enabled = !IS_CI) { ... } // duplicate code
        "test2".config(enabled = !IS_CI) { ... }
    }
}

Is there a full replacement for defaultTestCaseConfig.enabled in Kotest 5? That means it should enable/disable all tests in a spec according to a Boolean variable and be specified in a single place, not if the config block of every test.


Solution

  • Maybe the EnabledIf annotation can do what you want

    From the documentation:

    If we want to disable a spec dependent on the execution of a function, then we can use @EnabledIf.

    This annotation accepts a class that implements EnabledCondition, and that class is instantiated and invoked to determine if a spec is enabled. Note that implementations must have a zero args constructor.

    For example, we may wish to only execute tests containing the name "Linux" when run on a Linux machine.

    class LinuxOnlyCondition : EnabledCondition() {
      override fun enabled(kclass: KClass<out Spec>): Boolean = when {
        kclass.simpleName?.contains("Linux") == true -> IS_OS_LINUX
        else -> true // non Linux tests always run
      }
    }
    

    Then we can apply this condition to one or more specs:

    @EnabledIf(LinuxOnlyCondition::class)
    class MyLinuxTest1 : FunSpec() {
      // tests here
    }
    
    @EnabledIf(LinuxOnlyCondition::class)
    class MyLinuxTest2 : DescribeSpec() {
      // tests here
    }
    
    @EnabledIf(LinuxOnlyCondition::class)
    class MyWindowsTests : DescribeSpec() {
      // tests here
    }