Conditional Tests in ScalaTest

(, en)

Under some conditions you need to skip tests depending on (external) factors. It could be a package that might be missing or a database connection that is not available.

I found 3 options:

  1. cancel the test
  2. wrap the test in a helper function
  3. create a custom trait
// src/test/scala/ConditionalTestSpec.scala
import org.scalactic.source
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers

class ConditionalTestSpec extends AnyFlatSpec with Matchers with Conditionals {
  def isResourceAvailable = false

  // 1. CANCEL TEST
  it should "be cancelled" in {
    assume(isResourceAvailable, "db available")
    ???
  }

  private def whenConditionMetItShould(condition: => Boolean)(name: String)(testFun: => Any)(implicit
      pos: source.Position
  ): Unit =
    if (condition) it.should(name).in(testFun) else ignore.should(name).in(testFun)

  // 2. WRAP TEST WITH HELPER FUNCTION
  whenConditionMetItShould(isResourceAvailable)("be ignored, whenConditionMetItShould") {
    ???
  }

  // 3. CUSTOM TRAIT
  it should "be ignored, when" when isResourceAvailable in {
    ???
  }
}

trait Conditionals {
  this: AnyFlatSpec =>

  implicit class Conditional(verb: ItVerbString) {
    def when(condition: => Boolean): WhenWord = {
      new WhenWord(verb, condition)
    }
  }

  protected final class WhenWord(verb: ItVerbString, condition: => Boolean) {
    def in(testFun: => Any /* Assertion */ )(implicit pos: source.Position): Unit = {
      if (condition) verb.in(testFun) else verb.ignore(testFun)
    }
  }
}

See Also