Packages
testcontainers
1.9.0
2.3.1
2.3.0
2.2.0
2.1.0
2.1.0-rc1
2.0.0
2.0.0-rc3
2.0.0-rc2
2.0.0-rc
1.14.1
1.14.0
1.13.5
1.13.4
1.13.3
1.13.2
1.13.1
1.13.0
1.12.0
1.11.8
1.11.7
1.11.6
1.11.5
1.11.4
1.11.3
1.11.2
1.11.1
1.11.0
1.10.5
1.10.4
1.10.3
1.10.2
1.10.1
1.10.0
1.9.0
1.8.4
1.8.3
1.8.2
1.8.1
1.8.0
1.7.0
1.6.0
1.5.1
1.5.0
1.4.2
1.4.1
1.4.0
1.3.1
1.3.0
1.2.11
1.2.10
1.2.9
1.2.8
1.2.7
1.2.6
1.2.5
1.2.4
1.2.3
1.2.2
1.2.1
1.2.0
1.1.3
1.1.2
1.1.1
1.1.0
1.0.1
1.0.0
1.0.0-beta.1
1.0.0-beta
0.9.3
0.9.2
0.9.1
0.9.0
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.
Current section
72 Versions
Jump to
Current section
72 Versions
Compare versions
6
files changed
+106
additions
-87
deletions
| @@ -96,71 +96,28 @@ import Testcontainers.ExUnit | |
| 96 96 | container(:redis, Testcontainers.RedisContainer.new()) |
| 97 97 | ``` |
| 98 98 | |
| 99 | - ### In a Phoenix project: |
| 99 | + ### Run tests in a Phoenix project (or any project for that matter) |
| 100 100 | |
| 101 | - 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: |
| 101 | + To run/wrap testcontainers around a project use the testcontainers.test task. |
| 102 102 | |
| 103 | - ```elixir |
| 104 | - # in config/dev.exs: |
| 105 | - config :testcontainers, |
| 106 | - enabled: true |
| 107 | - database: "hello_dev" |
| 103 | + `mix testcontainers.test [--database postgres|mysql]` |
| 108 104 | |
| 109 | - # in config/test.exs: |
| 110 | - config :testcontainers, |
| 111 | - enabled: true |
| 105 | + to use postgres you can just run |
| 112 106 | |
| 113 | - # in lib/hello/application.ex: |
| 114 | - @impl true |
| 115 | - def start(_type, _args) do |
| 116 | - if Application.get_env(:testcontainers, :enabled, false) do |
| 117 | - {:ok, _container} = |
| 118 | - case Application.get_env(:testcontainers, :database) do |
| 119 | - nil -> |
| 120 | - Testcontainers.Ecto.postgres_container(app: :hello) |
| 107 | + `mix testcontainers.test` since postgres is default. |
| 121 108 | |
| 122 | - database -> |
| 123 | - Testcontainers.Ecto.postgres_container( |
| 124 | - app: :hello, |
| 125 | - persistent_volume_name: "#{database}_data" |
| 126 | - ) |
| 127 | - end |
| 128 | - end |
| 109 | + in your config/test.exs you can then change the repo config to this: |
| 129 110 | |
| 130 | - # .. other setup code |
| 131 | - end |
| 132 | - |
| 133 | - # in mix.exs |
| 134 | - # comment out test alias and setup aliases for ecto |
| 135 | - defp aliases do |
| 136 | - [ |
| 137 | - setup: [ |
| 138 | - "deps.get", |
| 139 | - # "ecto.setup", |
| 140 | - "assets.setup", |
| 141 | - "assets.build" |
| 142 | - ], |
| 143 | - # "ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"], |
| 144 | - # "ecto.reset": ["ecto.drop", "ecto.setup"], |
| 145 | - # test: ["ecto.create --quiet", "ecto.migrate --quiet", "test"], |
| 146 | - # ... SNIP |
| 147 | - ] |
| 148 | - end |
| 149 111 | ``` |
| 150 | - |
| 151 | - This will start a postgres container that will be terminated when the test process ends. |
| 152 | - |
| 153 | - 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. |
| 154 | - |
| 155 | - See documentation on [Testcontainers.Ecto](https://hexdocs.pm/testcontainers/Testcontainers.Ecto.html) for more information about the options it can take. |
| 156 | - |
| 157 | - 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: |
| 158 | - |
| 159 | - [Phoenix example](./examples/phoenix_project) |
| 160 | - |
| 161 | - There is also another example repo without Phoenix, just a bare mix project, which show cases that the ecto dependencies are in fact optional: |
| 162 | - |
| 163 | - [Mix project](./examples/mix_project) |
| 112 | + config :my_app, MyApp.Repo, |
| 113 | + username: System.get_env("DB_USER") || "postgres", |
| 114 | + password: System.get_env("DB_PASSWORD") || "postgres", |
| 115 | + hostname: System.get_env("DB_HOST") || "localhost", |
| 116 | + port: System.get_env("DB_PORT") || "5432", |
| 117 | + database: "my_app_test#{System.get_env("MIX_TEST_PARTITION")}", |
| 118 | + pool: Ecto.Adapters.SQL.Sandbox, |
| 119 | + pool_size: System.schedulers_online() * 2 |
| 120 | + ``` |
| 164 121 | |
| 165 122 | ### Logging |
| @@ -4,34 +4,38 @@ | |
| 4 4 | <<"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.">>}. |
| 5 5 | {<<"elixir">>,<<"~> 1.13">>}. |
| 6 6 | {<<"files">>, |
| 7 | - [<<"lib">>,<<"lib/connection">>,<<"lib/connection/dockerurl.ex">>, |
| 8 | - <<"lib/connection/docker_host_strategy.ex">>, |
| 9 | - <<"lib/connection/docker_host_strategy_evaluator.ex">>, |
| 10 | - <<"lib/connection/connection.ex">>, |
| 11 | - <<"lib/connection/docker_host_strategy">>, |
| 12 | - <<"lib/connection/docker_host_strategy/docker_socket_path.ex">>, |
| 13 | - <<"lib/connection/docker_host_strategy/docker_host_from_properties.ex">>, |
| 14 | - <<"lib/connection/docker_host_strategy/docker_host_from_env.ex">>, |
| 15 | - <<"lib/container.ex">>,<<"lib/exunit.ex">>,<<"lib/ecto.ex">>, |
| 16 | - <<"lib/docker">>,<<"lib/docker/api.ex">>,<<"lib/testcontainers.ex">>, |
| 17 | - <<"lib/container">>,<<"lib/container/mysql_container.ex">>, |
| 18 | - <<"lib/container/cassandra_container.ex">>, |
| 19 | - <<"lib/container/kafka_container.ex">>,<<"lib/container/protocols">>, |
| 20 | - <<"lib/container/protocols/container_builder.ex">>, |
| 21 | - <<"lib/container/selenium_container.ex">>, |
| 22 | - <<"lib/container/minio_container.ex">>, |
| 23 | - <<"lib/container/rabbitmq_container.ex">>, |
| 24 | - <<"lib/container/redis_container.ex">>,<<"lib/container/behaviours">>, |
| 25 | - <<"lib/container/behaviours/database.ex">>, |
| 26 | - <<"lib/container/emqx_container.ex">>,<<"lib/container/ceph_container.ex">>, |
| 27 | - <<"lib/container/postgres_container.ex">>,<<"lib/util">>, |
| 28 | - <<"lib/util/constants.ex">>,<<"lib/util/logger.ex">>, |
| 29 | - <<"lib/wait_strategy">>,<<"lib/wait_strategy/log_wait_strategy.ex">>, |
| 7 | + [<<"lib">>,<<"lib/ecto.ex">>,<<"lib/util">>,<<"lib/util/logger.ex">>, |
| 8 | + <<"lib/util/constants.ex">>,<<"lib/container.ex">>,<<"lib/exunit.ex">>, |
| 9 | + <<"lib/docker">>,<<"lib/docker/api.ex">>,<<"lib/wait_strategy">>, |
| 30 10 | <<"lib/wait_strategy/protocols">>, |
| 31 11 | <<"lib/wait_strategy/protocols/wait_strategy.ex">>, |
| 12 | + <<"lib/wait_strategy/port_wait_strategy.ex">>, |
| 32 13 | <<"lib/wait_strategy/command_wait_strategy.ex">>, |
| 33 | - <<"lib/wait_strategy/port_wait_strategy.ex">>,<<".formatter.exs">>, |
| 34 | - <<"mix.exs">>,<<"README.md">>,<<"LICENSE">>]}. |
| 14 | + <<"lib/wait_strategy/log_wait_strategy.ex">>,<<"lib/container">>, |
| 15 | + <<"lib/container/protocols">>, |
| 16 | + <<"lib/container/protocols/container_builder.ex">>, |
| 17 | + <<"lib/container/emqx_container.ex">>, |
| 18 | + <<"lib/container/redis_container.ex">>, |
| 19 | + <<"lib/container/rabbitmq_container.ex">>, |
| 20 | + <<"lib/container/selenium_container.ex">>, |
| 21 | + <<"lib/container/kafka_container.ex">>, |
| 22 | + <<"lib/container/mysql_container.ex">>, |
| 23 | + <<"lib/container/minio_container.ex">>, |
| 24 | + <<"lib/container/postgres_container.ex">>,<<"lib/container/behaviours">>, |
| 25 | + <<"lib/container/behaviours/database.ex">>, |
| 26 | + <<"lib/container/ceph_container.ex">>, |
| 27 | + <<"lib/container/cassandra_container.ex">>,<<"lib/connection">>, |
| 28 | + <<"lib/connection/connection.ex">>, |
| 29 | + <<"lib/connection/docker_host_strategy">>, |
| 30 | + <<"lib/connection/docker_host_strategy/docker_host_from_properties.ex">>, |
| 31 | + <<"lib/connection/docker_host_strategy/docker_host_from_env.ex">>, |
| 32 | + <<"lib/connection/docker_host_strategy/docker_socket_path.ex">>, |
| 33 | + <<"lib/connection/dockerurl.ex">>, |
| 34 | + <<"lib/connection/docker_host_strategy_evaluator.ex">>, |
| 35 | + <<"lib/connection/docker_host_strategy.ex">>,<<"lib/mix">>, |
| 36 | + <<"lib/mix/tasks">>,<<"lib/mix/tasks/testcontainers">>, |
| 37 | + <<"lib/mix/tasks/testcontainers/test.ex">>,<<"lib/testcontainers.ex">>, |
| 38 | + <<".formatter.exs">>,<<"mix.exs">>,<<"README.md">>,<<"LICENSE">>]}. |
| 35 39 | {<<"licenses">>,[<<"MIT">>]}. |
| 36 40 | {<<"links">>, |
| 37 41 | [{<<"GitHub">>, |
| @@ -58,4 +62,4 @@ | |
| 58 62 | {<<"optional">>,true}, |
| 59 63 | {<<"repository">>,<<"hexpm">>}, |
| 60 64 | {<<"requirement">>,<<"~> 3.3">>}]]}. |
| 61 | - {<<"version">>,<<"1.8.4">>}. |
| 65 | + {<<"version">>,<<"1.9.0">>}. |
| @@ -1,4 +1,6 @@ | |
| 1 1 | defmodule Testcontainers.Ecto do |
| 2 | + @deprecated "This feature is deprecated and will be removed in a future release. Please call `mix testcontainers.test` instead." |
| 3 | + |
| 2 4 | @moduledoc """ |
| 3 5 | Facilitates the creation of a Postgres or MySql container for testing with Ecto. |
| @@ -0,0 +1,56 @@ | |
| 1 | + defmodule Mix.Tasks.Testcontainers.Test do |
| 2 | + use Mix.Task |
| 3 | + alias Testcontainers.PostgresContainer |
| 4 | + alias Testcontainers.MySqlContainer |
| 5 | + |
| 6 | + @shortdoc "Runs tests with a Postgres container" |
| 7 | + def run(args) do |
| 8 | + Application.ensure_all_started(:tesla) |
| 9 | + Application.ensure_all_started(:hackney) |
| 10 | + {:ok, _} = Testcontainers.start_link() |
| 11 | + |
| 12 | + {opts, _, _} = OptionParser.parse(args, switches: [ |
| 13 | + database: :string |
| 14 | + ]) |
| 15 | + |
| 16 | + database = opts[:database] || "postgres" |
| 17 | + |
| 18 | + {container, port} = case database do |
| 19 | + "postgres" -> |
| 20 | + {:ok, container} = Testcontainers.start_container( |
| 21 | + PostgresContainer.new() |
| 22 | + |> PostgresContainer.with_user("test") |
| 23 | + |> PostgresContainer.with_password("test") |
| 24 | + ) |
| 25 | + port = PostgresContainer.port(container) |
| 26 | + {container, port} |
| 27 | + "mysql" -> |
| 28 | + {:ok, container} = Testcontainers.start_container( |
| 29 | + MySqlContainer.new() |
| 30 | + |> MySqlContainer.with_user("test") |
| 31 | + |> MySqlContainer.with_password("test") |
| 32 | + ) |
| 33 | + port = MySqlContainer.port(container) |
| 34 | + {container, port} |
| 35 | + _ -> Mix.raise("Unsupported database: #{database}") |
| 36 | + end |
| 37 | + |
| 38 | + env = [ |
| 39 | + {"DB_USER", "test"}, |
| 40 | + {"DB_PASSWORD", "test"}, |
| 41 | + {"DB_HOST", Testcontainers.get_host()}, |
| 42 | + {"DB_PORT", port |> Integer.to_string()} |
| 43 | + ] |
| 44 | + |
| 45 | + try do |
| 46 | + {output, exit_code} = System.cmd("mix", ["test"], env: env) |
| 47 | + if exit_code != 0 do |
| 48 | + IO.puts(output) |
| 49 | + raise "\u274c Tests failed" |
| 50 | + end |
| 51 | + IO.puts("\u2705 Tests passed") |
| 52 | + after |
| 53 | + Testcontainers.stop_container(container.container_id) |
| 54 | + end |
| 55 | + end |
| 56 | + end |
| @@ -2,7 +2,7 @@ defmodule Testcontainers.Constants do | |
| 2 2 | @moduledoc false |
| 3 3 | |
| 4 4 | def library_name, do: :testcontainers |
| 5 | - def library_version, do: "1.8.4" |
| 5 | + def library_version, do: "1.9.0" |
| 6 6 | def container_label, do: "org.testcontainers" |
| 7 7 | def container_lang_label, do: "org.testcontainers.lang" |
| 8 8 | def container_lang_value, do: Elixir |> Atom.to_string() |> String.downcase() |
Loading more files…