Testcontainers is an Elixir library that supports ExUnit tests, providing lightweight, throwaway instances of common databases, Selenium web browsers, or anything else that can run in a Docker container.
Before you begin, ensure you have met the following requirements:
- You have installed the latest version of Elixir
- You have a Docker runtime installed
- You are familiar with Elixir and Docker basics
To add Testcontainers to your project, follow these steps:
- Add
testcontainers
to your list of dependencies inmix.exs
:
def deps do
[
{:testcontainers, "~> x.x.x"}
]
end
-
Run mix deps.get
-
Add the following to test/test_helper.exs
Testcontainers.start_link()
This section explains how to use the Testcontainers library in your own project.
You can use generic container api, where you have to define everything yourself:
{:ok, _} = Testcontainers.start_link()
config = %Testcontainers.Container{image: "redis:5.0.3-alpine"}
{:ok, container} = Testcontainers.start_container(config)
Or you can use one of many predefined containers like RedisContainer
, that has waiting strategies among other things defined up front with good defaults:
{:ok, _} = Testcontainers.start_link()
config = Testcontainers.RedisContainer.new()
{:ok, container} = Testcontainers.start_container(config)
Given you have added Testcontainers.start_link() to test_helper.exs:
setup
config = Testcontainers.RedisContainer.new()
{:ok, container} = Testcontainers.start_container(config)
ExUnit.Callbacks.on_exit(fn -> Testcontainers.stop_container(container.container_id) end)
{:ok, %{redis: container}}
end
there is a macro that can simplify this down to a oneliner:
import Testcontainers.ExUnit
container(:redis, Testcontainers.RedisContainer.new())
To start a postgres container when running tests, that also enables testing of application initialization with database calls at startup, add this in application.ex:
# in config/dev.exs:
config :testcontainers,
enabled: true
database: "hello_dev"
# in config/test.exs:
config :testcontainers,
enabled: true
# in lib/hello/application.ex:
@impl true
def start(_type, _args) do
if Application.get_env(:testcontainers, :enabled, false) do
{:ok, _container} =
case Application.get_env(:testcontainers, :database) do
nil ->
Testcontainers.Ecto.postgres_container(app: :hello)
database ->
Testcontainers.Ecto.postgres_container(
app: :hello,
persistent_volume_name: "#{database}_data"
)
end
end
# .. other setup code
end
# in mix.exs
# comment out test alias and setup aliases for ecto
defp aliases do
[
setup: [
"deps.get",
# "ecto.setup",
"assets.setup",
"assets.build"
],
# "ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"],
# "ecto.reset": ["ecto.drop", "ecto.setup"],
# test: ["ecto.create --quiet", "ecto.migrate --quiet", "test"],
# ... SNIP
]
end
This will start a postgres container that will be terminated when the test process ends.
The database config in config/test.exs will be temporarily updated in-memory with the random host port on the container, and other properties like username, password and database. In most cases these will default to "test" unless overridden.
See documentation on Testcontainers.Ecto for more information about the options it can take.
There is an example repo here with a bare bones phoenix application, where the only changes are the use of the ecto function and removing the test alias that interferes with it:
There is also another example repo without Phoenix, just a bare mix project, which show cases that the ecto dependencies are in fact optional:
By default, Testcontainers doesn't log anything. If you want Testcontainers to log, set the desired log level in config/test.exs:
# config/test.exs
import Config
config :testcontainers,
log_level: :warning
For more detailed information about the API, different container configurations, and advanced usage scenarios, please refer to the API documentation.
We welcome your contributions! Please see our contributing guidelines (TBD) for more details on how to submit patches and the contribution workflow.
Testcontainers is available under the MIT license. See the LICENSE file for more info.
If you have any questions, issues, or want to contribute, feel free to contact us.
Thank you for using Testcontainers to test your Elixir applications!