Current section

72 Versions

Jump to

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…