Scala wrapper for testcontainers-java that
allows using docker containers for functional/integration/unit testing.
TestContainers is a Java 8 library that supports JUnit tests, providing lightweight, throwaway instances of common databases, Selenium web browsers, or anything else that can run in a Docker container.
Testcontainers-scala in action: http://dimafeng.com/2016/08/01/testcontainers-selenium/
SBT
libraryDependencies += "com.dimafeng" %% "testcontainers-scala" % testcontainersScalaVersion % "test"- JDK >= 1.8
- See 'Compatibility' section
There are two ScalaTest aware traits:
ForEachTestContainerstarts a new container(s) before each test case and then stops and removes it.ForAllTestContainerstarts and stops a container only once for all test cases within the spec.
To start using it, you just need to extend one of those traits and override a container val as follows:
import com.dimafeng.testcontainers.{ForAllTestContainer, MySQLContainer}
class MysqlSpec extends FlatSpec with ForAllTestContainer {
override val container = MySQLContainer()
it should "do something" in {
Class.forName(container.driverClassName)
val connection = DriverManager.getConnection(container.jdbcUrl, container.username, container.password)
...
}
}This spec has a clean mysql database instance for each of its test cases.
import org.testcontainers.containers.MySQLContainer
class MysqlSpec extends FlatSpec with ForAllTestContainer {
override val container = MySQLContainer()
it should "do something" in {
...
}
it should "do something 2" in {
...
}
}This spec starts one container and both tests share the container's state.
The most flexible but less convenient container type is GenericContainer. This container allows to launch any docker image
with custom configuration.
class GenericContainerSpec extends FlatSpec with ForAllTestContainer {
override val container = GenericContainer("nginx:latest",
exposedPorts = Seq(80),
waitStrategy = Wait.forHttp("/")
)
"GenericContainer" should "start nginx and expose 80 port" in {
assert(Source.fromInputStream(
new URL(s"http://${container.containerIpAddress}:${container.mappedPort(80)}/").openConnection().getInputStream
).mkString.contains("If you see this page, the nginx web server is successfully installed"))
}
}class ComposeSpec extends FlatSpec with ForAllTestContainer {
override val container = DockerComposeContainer(new File("src/test/resources/docker-compose.yml"), exposedServices = Seq(ExposedService("redis_1", 6379)))
"DockerComposeContainer" should "retrieve non-0 port for any of services" in {
assert(container.getServicePort("redis_1", 6379) > 0)
}
}Before you can use this type of containers, you need to add the following dependencies to your project:
"org.seleniumhq.selenium" % "selenium-java" % "2.53.1"
and
"org.testcontainers" % "selenium" % "1.8.0"
Now you can write a test in this way:
class SeleniumSpec extends FlatSpec with SeleniumTestContainerSuite with WebBrowser {
override def desiredCapabilities = DesiredCapabilities.chrome()
"Browser" should "show google" in {
go to "http://google.com"
}
}
In this case, you'll obtain a clean instance of browser (firefox/chrome) within container to which a test will connect via remote-driver. See Webdriver Containers for more details.
Requires you to add this dependency
class MysqlSpec extends FlatSpec with ForAllTestContainer {
override val container = MySQLContainer()
"Mysql container" should "be started" in {
Class.forName(container.driverClassName)
val connection = DriverManager.getConnection(container.jdbcUrl, container.username, container.password)
...
}
}The container can also be customized using the constructor parameters, this snippet will initialize a docker container from a specific docker image, with a specific schema name and specific username/password
class MysqlSpec extends FlatSpec with ForAllTestContainer {
override val container = MySQLContainer(mysqlImageVersion = "mysql:5.7.18",
databaseName = "testcontainer-scala",
username = "scala",
password = "scala")
"Mysql container" should "be started" in {
Class.forName(container.driverClassName)
val connection = DriverManager.getConnection(container.jdbcUrl, container.username, container.password)
...
}
}Requires you to add this dependency
class PostgresqlSpec extends FlatSpec with ForAllTestContainer {
override val container = PostgreSQLContainer()
"PostgreSQL container" should "be started" in {
Class.forName(container.driverClassName)
val connection = DriverManager.getConnection(container.jdbcUrl, container.username, container.password)
...
}
}If you need to test more than one container in your test, you could use MultipleContainers for that. Just define your containers and pass them to the MultipleContainers constructor:
val mySqlContainer = MySQLContainer()
val genericContainer = GenericContainer(...)
override val container = MultipleContainers(mySqlContainer, genericContainer)If configuration of one container depends on runtime state of another one, you should define your containers as lazy:
lazy val container1 = Container1()
lazy val container2 = Container2(container1.port)
override val container = MultipleContainers(container1, container2)This container will allow you to map container ports to statically defined ports on the docker host.
...
val container = FixedHostPortGenericContainer("nginx:latest",
waitStrategy = Wait.forHttp("/"),
exposedHostPort = 8090,
exposedContainerPort = 80
)All container types have constructor methods with most popular parameters. In case you're missing some custom option from testcontainers-java, there is
a method that provides an elegant way to tune the nested container. It's not recommended to access inner container directly.
override val container = MySQLContainer().configure { c =>
c.withNetwork(...)
c.withStartupAttempts(...)
}
If you want to execute your code after container start or before container stop you can override afterStart() and beforeStop() methods.
class MysqlSpec extends FlatSpec with ForAllTestContainer {
...
override def beforeStop(): Unit = {
// your code
}
override def afterStart(): Unit = {
// your code
}
}-
0.32.0
- TestContainers ->
1.12.1 - SBT ->
1.3.0
- TestContainers ->
-
0.31.0
- Additional config options for PostgreSQL #70
-
0.30.0
- TestContainers ->
1.12.0 - Scala ->
2.12.9
- TestContainers ->
-
0.29.0
- TestContainers
1.11.2->1.11.4
- TestContainers
-
0.28.0
VaultContainer
-
0.27.0
- New
TestLifecycleAwaretrait introduced. You can use it when you want to do something with the container before or after the test. Containernow implementsStartableinterface withstartandstopmethods.- Old container's lifecycle methods
finished,succeeded,starting,failedare deprecated. Usestart,stop, andTestLifecycleAwaremethods instead. - Added
KafkaContainer - Added
CassandraContainer
- New
-
0.26.0
- TestContainers
1.11.2->1.11.3 - Scala 2.13.0
- TestContainers
-
0.25.0
- TestContainers
1.11.1->1.11.2
- TestContainers
-
0.24.0
- TestContainers
1.10.6->1.11.1 - Scala 2.13.0-M5
- TestContainers
-
0.23.0
- TestContainers
1.10.1->1.10.6
- TestContainers
-
0.22.0
- TestContainers
1.9.1->1.10.1
- TestContainers
-
0.21.0
- TestContainers
1.8.3->1.9.1
- TestContainers
-
0.20.0
- TestContainers
1.8.0->1.8.3
- TestContainers
-
0.19.0
- TestContainers
1.7.3->1.8.0 - (#24)
DockerComposeContainerenhancements - Added Dockerfile support to
GenericContainer
- TestContainers
-
0.18.0
- TestContainers
1.7.1->1.7.3
- TestContainers
-
0.17.0
- Testcontainers
1.6.0->1.7.1 - Removed
shapelessdependency - Added implicit conversion to
LazyContainer. This gives you a possibility to not wrap your containers into theLazyContainermanually. MultipleContainers.applynow receivesLazyContainer[_]*type. Together with the previous point, it makes usage experience ofMultipleContainersmore smooth.- Added multiple missing reflecting methods to all containers
- Added
configuremethod. See this for more details
- Testcontainers
-
0.16.0
FixedHostPortGenericContaineradded
-
0.15.0
- Additional configuration parameters for
MySQLContainer - Improvements to
MultipleContainers- container lazy creation for dependent containers
- Additional configuration parameters for
-
0.14.0
- TestContainers
1.5.1->1.6.0
- TestContainers
-
0.13.0
- TestContainers
1.4.3->1.5.1 - Scala 2.10 support
- TestContainers
-
0.12.0
- Improvement:
afterStarthook now handles exceptions correctly
- Improvement:
-
0.11.0
- Improvement: containers don't start in
ForAllTestContainerif all tests are ignored
- Improvement: containers don't start in
-
0.10.0
- TestContainers
1.4.2->1.4.3 - Fix of #8
- TestContainers
-
0.8.0
- PostgreSQL container
-
0.7.0
- TestContainers
1.2.1->1.4.2
- TestContainers
-
0.6.0
- TestContainers
1.2.0->1.2.1 - Fix of the
afterStarthook
- TestContainers
-
0.5.0
- TestContainers
1.1.8->1.2.0
- TestContainers
-
0.4.1
- TestContainers
1.1.7->1.1.8
- TestContainers
-
0.4.0
- TestContainers
1.1.5->1.1.7 - Scala cross-building (2.11.* + 2.12.*)
- TestContainers
-
0.3.0
- TestContainers
1.1.0->1.1.5 - Start/Stop hooks
- TestContainers
-
0.2.0
- TestContainers
1.0.5->1.1.0 - Code refactoring
- Scala wrappers for major container types
- TestContainers
$ sbt clean release
