All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.dimafeng.testcontainers.scalatest.TestContainersForAll.scala Maven / Gradle / Ivy

package com.dimafeng.testcontainers.scalatest

import org.scalatest.{Args, CompositeStatus, Status, Suite}

/**
  * Starts containers before all tests and stop then after all tests
  *
  * Example:
  * {{{
  * class ExampleSpec extends FlatSpec with TestContainersForAll {
  *
  *   // First of all, you need to declare, which containers you want to use
  *   override type Containers = MySQLContainer and PostgreSQLContainer
  *
  *   // After that, you need to describe, how you want to start them,
  *   // In this method you can use any intermediate logic.
  *   // You can pass parameters between containers, for example.
  *   override def startContainers(): Containers = {
  *     val container1 = MySQLContainer.Def().start()
  *     val container2 = PostgreSQLContainer.Def().start()
  *     container1 and container2
  *   }
  *
  *   // `withContainers` function supports multiple containers:
  *   it should "test" in withContainers { case mysqlContainer and pgContainer =>
  *     // Inside your test body you can do with your containers whatever you want to
  *     assert(mysqlContainer.jdbcUrl.nonEmpty && pgContainer.jdbcUrl.nonEmpty)
  *   }
  *
  * }
  * }}}
  */
trait TestContainersForAll extends TestContainersSuite { self: Suite =>

  abstract override def run(testName: Option[String], args: Args): Status = {
    if (expectedTestCount(args.filter) == 0) {
      new CompositeStatus(Set.empty)
    } else {
      val containers = startContainers()
      startedContainers = Some(containers)
      try {
        afterContainersStart(containers)
        super.run(testName, args)
      } finally {
        try {
          beforeContainersStop(containers)
        }
        finally {
          try {
            startedContainers.foreach(_.stop())
          }
          finally {
            startedContainers = None
          }
        }
      }
    }
  }

  abstract protected override def runTest(testName: String, args: Args): Status = {
    @volatile var testCalled = false
    @volatile var afterTestCalled = false

    try {
      startedContainers.foreach(beforeTest)

      testCalled = true
      val status = super.runTest(testName, args)

      afterTestCalled = true
      if (!status.succeeds()) {
        val err = new RuntimeException("Test failed")
        startedContainers.foreach(afterTest(_, Some(err)))
      } else {
        startedContainers.foreach(afterTest(_, None))
      }

      status
    }
    catch {
      case e: Throwable =>
        if (testCalled && !afterTestCalled) {
          afterTestCalled = true
          startedContainers.foreach(afterTest(_, Some(e)))
        }

        throw e
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy