2020-06-04 08:44:03 +00:00
# clj-test-containers
2020-06-06 15:49:03 +00:00
[](http://clojars.org/clj-test-containers)
2020-06-04 08:58:10 +00:00
## What it is
2022-03-25 21:59:14 +00:00
2020-10-24 08:17:50 +00:00
This library is a lightweight wrapper around the [Testcontainers Java library ](https://www.testcontainers.org/ ).
2020-06-04 08:58:10 +00:00
## What it isn't
2022-03-25 21:59:14 +00:00
This library does not provide tools to include testcontainers in your testing lifecycle. As there are many different
test tools with different approaches to testing in the clojure world, handling the lifecycle is up to you.
2020-06-04 08:58:10 +00:00
2022-03-21 18:24:33 +00:00
## Integration with test runners
2022-03-25 21:59:14 +00:00
2022-03-21 18:24:33 +00:00
There is an [experimental kaocha plugin ](https://github.com/lambdaschmiede/kaocha-testcontainers-plugin ) you can try out
2020-06-04 08:44:03 +00:00
## Usage
2020-06-06 15:30:00 +00:00
2022-03-25 21:59:14 +00:00
The library provides a set of functions to interact with the testcontainers. A simple example, how to create a container
with a Docker label, could look like this:
2020-06-06 15:30:00 +00:00
2020-06-04 11:04:30 +00:00
```clojure
(require '[clj-test-containers.core :as tc])
2020-06-04 08:44:03 +00:00
2022-03-25 21:59:14 +00:00
(def container (-> (tc/create {:image-name "postgres:12.1"
2020-07-16 20:44:26 +00:00
:exposed-ports [5432]
2022-03-25 21:59:14 +00:00
:env-vars {"POSTGRES_PASSWORD" "verysecret"}})
(tc/bind-filesystem! {:host-path "/tmp"
2020-07-16 20:44:26 +00:00
:container-path "/opt"
2022-03-25 21:59:14 +00:00
:mode :read-only})
2021-06-01 17:52:04 +00:00
(tc/start!)))
2020-06-06 15:30:00 +00:00
(do-database-testing (:host container)
(get (:mapped-ports container) 5432))
(tc/stop! container)
```
2020-08-05 05:13:31 +00:00
2020-08-05 20:34:49 +00:00
If you'd rather create a container from a Dockerfile in your project, it could look like this:
2020-08-05 05:13:31 +00:00
```clojure
2020-08-05 20:34:49 +00:00
(require '[clj-test-containers.core :as tc])
2022-03-25 21:59:14 +00:00
(def container (-> (tc/create-from-docker-file {:env-vars {"FOO" "bar"}
:exposed-ports [80]
:docker-file "resources/Dockerfile"})
(tc/start!)))
2020-08-05 20:34:49 +00:00
```
If you prefer to use prebuilt containers from the Testcontainers project, you can do it like this
```clojure
(require '[clj-test-containers.core :as tc])
(:import [org.testcontainers.containers PostgreSQLContainer])
2022-03-25 21:59:14 +00:00
(def container (-> (tc/init {:container (PostgreSQLContainer. "postgres:12.2")
:exposed-ports [5432]})
(tc/start!)))
2020-08-05 05:13:31 +00:00
```
2020-06-06 15:30:00 +00:00
## Functions and Properties
### create
2022-03-25 21:59:14 +00:00
2020-09-26 07:59:28 +00:00
Creates a testcontainers instance from a given Docker label and returns them
2020-08-05 20:34:49 +00:00
#### Config parameters:
2022-03-26 10:54:28 +00:00
| Key | Type | Description |
| ------------- | :------------- |:----------------------------------------------------------------------------------------------------|
| `:image-name` | String, mandatory | The name and label of an image, e.g. `postgres:12.2` |
| `:exposed-ports` | Vector with ints, mandatory | All ports which should be exposed and mapped to a local port |
| `:env-vars` | Map | A map with environment variables |
| `:command` | Vector with strings | The start command of the container |
| `:network` | Map | A map containing the configuration of a Docker Network (see: `create-network` ) |
| `:network-aliases` | Map | A list of alias names for the container on the network |
2022-03-26 10:56:58 +00:00
| `:wait-for` | Map | A map containing the [wait strategy ](doc/wait-strategies.md ) to use and the condition to check for |
| `:log-to` | Map | A map containing the [log strategy ](doc/log-strategies.md ) to use, e.g. {:log-strategy string} |
2020-08-05 20:34:49 +00:00
2020-09-26 07:59:28 +00:00
#### Result:
2020-08-05 20:34:49 +00:00
2020-10-23 21:12:24 +00:00
| Key | Type | Description |
| ------------- | :------------- | :----- |
| `:container` | `org.testcontainers.containers.Container` | The Testcontainers instance, accessible for everything this library doesn't provide (yet) |
| `:exposed-ports` | Vector with ints | Value of the same input parameter |
| `:env-vars` | Map | Value of the same input parameter |
| `:host` | String | The host for the Docker Container |
| `:network` | Map | The network configuration of the Container, if provided |
| `:wait-for` | Map | The wait-for configuration of the Container, if provided! |
2020-08-05 20:34:49 +00:00
#### Example:
```clojure
2022-03-25 21:59:14 +00:00
(create {:image-name "alpine:3.2"
:exposed-ports [80]
:env-vars {"MAGIC_NUMBER" "42"}
:network (create-network)
2020-08-05 20:34:49 +00:00
:network-aliases ["api-server"]
2022-03-25 21:59:14 +00:00
:command ["/bin/sh"
"-c"
"while true; do echo \"$MAGIC_NUMBER\" | nc -l -p 80; done"]})
2020-09-26 07:59:28 +00:00
```
#### Example using wait-for and healthcheck:
```clojure
2022-03-25 21:59:14 +00:00
(create {:image-name "alpine:3.2"
:exposed-ports [80]
:env-vars {"MAGIC_NUMBER" "42"}
:network (create-network)
2020-09-26 07:59:28 +00:00
:network-aliases ["api-server"]
2022-03-25 21:59:14 +00:00
:wait-for {:strategy :health}
:command ["/bin/sh"
"-c"
"while true; do echo \"$MAGIC_NUMBER\" | nc -l -p 80; done"]})
2020-08-05 20:34:49 +00:00
```
### init
2022-03-25 21:59:14 +00:00
2020-08-05 20:34:49 +00:00
Initializes a given Testcontainer, which was e.g. provided by a library
2020-06-06 15:30:00 +00:00
#### Config parameters:
2022-03-26 10:54:28 +00:00
| Key | Type | Description |
| ------------- | :------------- |:----------------------------------------------------------------------------------------------------|
| `:container` | `org.testcontainers.containers.GenericContainer` , mandatory | The name and label of an image, e.g. `postgres:12.2` |
| `:exposed-ports` | Vector with ints, mandatory | All ports which should be exposed and mapped to a local port |
| `:env-vars` | Map | A map with environment variables |
| `:command` | Vector with strings | The start command of the container |
| `:network` | Map | A map containing the configuration of a Docker Network (see: `create-network` ) |
| `:network-aliases` | Map | A list of alias names for the container on the network |
2022-03-26 10:56:58 +00:00
| `:wait-for` | Map | A map containing the [wait strategy ](doc/wait-strategies.md ) to use and the condition to check for |
| `:log-to` | Map | A map containing the [log strategy ](doc/log-strategies.md ) to use, e.g. {:log-strategy string} |
2022-03-26 10:54:28 +00:00
| | | |
2022-03-25 21:59:14 +00:00
2020-09-26 07:59:28 +00:00
#### Result:
2020-06-06 15:30:00 +00:00
2020-10-23 21:12:24 +00:00
| Key | Type | Description |
2022-03-26 10:54:28 +00:00
| ------------- | :------------- |:------------------------------------------------------------------------------------------|
2020-10-23 21:12:24 +00:00
| `:container` | `org.testcontainers.containers.Container` | The Testcontainers instance, accessible for everything this library doesn't provide (yet) |
| `:exposed-ports` | Vector with ints | Value of the same input parameter |
| `:env-vars` | Map | Value of the same input parameter |
| `:host` | String | The host for the Docker Container |
| `:network` | Map | The network configuration of the Container, if provided |
| `:wait-for` | Map | The wait-for configuration of the Container, if provided! |
2020-06-06 15:30:00 +00:00
#### Example:
```clojure
2020-08-05 20:34:49 +00:00
;; PostgreSQL container needs a separate library! This is not included.
2022-03-25 21:59:14 +00:00
(init {:container (org.testcontainers.containers.PostgreSQLContainer)
2020-08-05 20:37:43 +00:00
:exposed-ports [80]
2022-03-25 21:59:14 +00:00
:env-vars {"MAGIC_NUMBER" "42"}
:command ["/bin/sh"
"-c"
"while true; do echo \"$MAGIC_NUMBER\" | nc -l -p 80; done"]})
2020-09-26 07:59:28 +00:00
```
#### Example using wait-for and a log message:
```clojure
;; PostgreSQL container needs a separate library! This is not included.
2022-03-25 21:59:14 +00:00
(init {:container (org.testcontainers.containers.PostgreSQLContainer)
2020-09-26 07:59:28 +00:00
:exposed-ports [80]
2022-03-25 21:59:14 +00:00
:env-vars {"MAGIC_NUMBER" "42"}
:wait-for {:strategy :log :message "accept connections"}
:command ["/bin/sh"
"-c"
"while true; do echo \"$MAGIC_NUMBER\" | nc -l -p 80; done"]})
2020-08-05 20:34:49 +00:00
```
### create-from-docker-file
2022-03-25 21:59:14 +00:00
2020-08-05 20:34:49 +00:00
Creates a testcontainer from a Dockerfile
#### Config parameters:
2020-10-23 21:12:24 +00:00
| Key | Type | Description |
| ------------- | :------------- | :----- |
| `:docker-file` | String, mandatory | String containing a path to a Dockerfile |
| `:exposed-ports` | Vector with ints, mandatory | All ports which should be exposed and mapped to a local port |
| `:env-vars` | Map | A map with environment variables |
| `:command` | Vector with strings | The start command of the container |
| `:network` | Map | A map containing the configuration of a Docker Network (see: `create-network` ) |
| `:network-aliases` | Map | A list of alias names for the container on the network |
2022-03-26 10:56:58 +00:00
| `:wait-for` | Map | A map containing the [wait strategy ](doc/wait-strategies.md ) to use and the condition to check for |
| `:log-to` | Map | A map containing the [log strategy ](doc/log-strategies.md ) to use, e.g. {:log-strategy string} |
2020-10-23 21:12:24 +00:00
| | | |
2022-03-25 21:59:14 +00:00
2020-09-26 07:59:28 +00:00
#### Result:
2020-08-05 20:34:49 +00:00
2020-10-23 21:12:24 +00:00
| Key | Type | Description |
| ------------- | :------------- | :----- |
| `:container` | `org.testcontainers.containers.Container` | The Testcontainers instance, accessible for everything this library doesn't provide (yet) |
| `:exposed-ports` | Vector with ints | Value of the same input parameter |
| `:env-vars` | Map | Value of the same input parameter |
| `:host` | String | The host for the Docker Container |
| `:network` | Map | The network configuration of the Container, if provided |
| `:wait-for` | Map | The wait-for configuration of the Container, if provided! |
2020-08-05 20:34:49 +00:00
#### Example:
```clojure
2022-03-25 21:59:14 +00:00
(create-from-docker-file {:docker-file "resources/Dockerfile"
2020-08-05 20:37:43 +00:00
:exposed-ports [5432]
2022-03-25 21:59:14 +00:00
:env-vars {"MAGIC_NUMBER" "42"}
:command ["/bin/sh"
"-c"
"while true; do echo \"$MAGIC_NUMBER\" | nc -l -p 80; done"]})
2020-06-06 15:30:00 +00:00
```
2020-06-06 15:35:43 +00:00
---
2020-06-06 15:30:00 +00:00
### start!
2022-03-25 21:59:14 +00:00
2020-06-06 15:30:00 +00:00
Starts the Testcontainer, which was defined by `create`
#### Config parameters:
2020-10-23 21:12:24 +00:00
| Key | Type | Description |
| ------------- | :------------- | :----- |
| First parameter: | | |
| `container-config` | Map, mandatory | Return value of the `create` function |
| | | |
2020-06-06 15:30:00 +00:00
2020-09-26 07:59:28 +00:00
#### Result:
2022-03-25 21:59:14 +00:00
2020-10-23 21:12:24 +00:00
| Key | Type | Description |
| ------------- | :------------- | :----- |
| `:container` | `org.testcontainers.containers.Container` | The Testcontainers instance, accessible for everything this library doesn't provide (yet) |
| `:exposed-ports` | Vector with ints | Value of the same input parameter |
| `:env-vars` | Map | Value of the same input parameter |
| `:host` | String | The host for the Docker Container |
| `:id` | String | The ID of the started docker container |
| `:mapped-ports` | Map | A map containing the container port as key and the mapped local port as a value |
2020-06-06 15:30:00 +00:00
#### Example:
```clojure
2022-03-25 21:59:14 +00:00
(def container (create {:image-name "alpine:3.2"
2020-06-06 15:30:00 +00:00
:exposed-ports [80]
2022-03-25 21:59:14 +00:00
:env-vars {"MAGIC_NUMBER" "42"}}))
2020-09-26 07:59:28 +00:00
(start! container)
2020-06-06 15:30:00 +00:00
```
2020-06-06 15:35:43 +00:00
---
2020-06-06 15:30:00 +00:00
### stop!
2022-03-25 21:59:14 +00:00
2020-06-06 15:30:00 +00:00
Stops the Testcontainer, which was defined by `create`
#### Config parameters:
2020-10-23 21:12:24 +00:00
| Key | Type | Description |
| ------------- | :------------- | :----- |
| First parameter: | | |
| `container-config` | Map, mandatory | Return value of the `create` function |
2020-06-06 15:30:00 +00:00
2020-09-26 07:59:28 +00:00
#### Result:
2022-03-25 21:59:14 +00:00
2020-06-06 15:30:00 +00:00
The `container-config`
#### Example:
```clojure
2022-03-25 21:59:14 +00:00
(def container (create {:image-name "alpine:3.2"
2020-06-06 15:30:00 +00:00
:exposed-ports [80]
2022-03-25 21:59:14 +00:00
:env-vars {"MAGIC_NUMBER" "42"}}))
2020-09-26 07:59:28 +00:00
(start! container)
(stop! container)
2020-06-06 15:30:00 +00:00
```
2020-06-06 15:35:43 +00:00
---
2020-06-06 15:30:00 +00:00
### map-classpath-resource!
2022-03-25 21:59:14 +00:00
2020-06-06 15:30:00 +00:00
Maps a resource from your classpath into the containers file system
#### Config parameters:
2022-03-25 21:59:14 +00:00
| Key | Type | Description |
2020-06-06 15:30:00 +00:00
| ------------- |:------------- | :-----|
| First parameter: | | |
| `container-config` | Map, mandatory | Return value of the `create` function |
| Second parameter: | | |
2022-03-25 21:59:14 +00:00
| `:resource-path` | String, mandatory | Path of your classpath resource |
| `:container-path` | String, mandatory | Path, to which the resource should be mapped |
| `:mode` | Keyword, mandatory | `:read-only` or `:read-write` |
2020-06-04 11:04:30 +00:00
2020-09-26 07:59:28 +00:00
#### Result:
2022-03-25 21:59:14 +00:00
2020-06-06 15:30:00 +00:00
The `container-config`
#### Example:
```clojure
2022-03-25 21:59:14 +00:00
(map-classpath-resource! container {:resource-path "test.sql"
:container-path "/opt/test.sql"
:mode :read-only})
2020-06-04 11:04:30 +00:00
```
2020-06-04 08:44:03 +00:00
2020-06-06 15:35:43 +00:00
---
2020-06-06 15:30:00 +00:00
### bind-filesystem!
2022-03-25 21:59:14 +00:00
2020-06-06 15:30:00 +00:00
Binds a path from your local filesystem into the Docker container as a volume
#### Config parameters:
2020-10-23 21:12:24 +00:00
| Key | Type | Description |
| ------------- | :------------- | :----- |
| First parameter: | | |
| `container-config` | Map, mandatory | Return value of the `create` function |
| Second parameter: | | |
| `:host-path` | String , mandatory | Path on your local filesystem |
| `:container-path` | String, mandatory | Path, to which the resource should be mapped |
| `:mode` | Keyword, mandatory | `:read-only` or `:read-write` |
2020-06-06 15:30:00 +00:00
2020-09-26 07:59:28 +00:00
#### Result:
2022-03-25 21:59:14 +00:00
2020-06-06 15:30:00 +00:00
The `container-config`
#### Example:
```clojure
2022-03-25 21:59:14 +00:00
(bind-filesystem! container {:host-path "."
2020-06-06 15:30:00 +00:00
:container-path "/opt"
2022-03-25 21:59:14 +00:00
:mode :read-only})
2020-06-06 15:30:00 +00:00
```
2020-06-06 15:35:43 +00:00
---
2020-06-06 15:30:00 +00:00
### copy-file-to-container!
2022-03-25 21:59:14 +00:00
2020-06-06 15:30:00 +00:00
Copies a file from your filesystem or classpath into the running container
#### Config parameters:
2022-03-25 21:59:14 +00:00
| Key | Type | Description |
2020-06-06 15:30:00 +00:00
| ------------- |:------------- | :-----|
| First parameter: | | |
| `container-config` | Map, mandatory | Return value of the `create` function |
| Second parameter: | | |
2022-03-25 21:59:14 +00:00
| `:path` | String, mandatory | Path to a classpath resource *or* file on your filesystem |
2022-10-06 09:44:46 +00:00
| `:container-path` | String, mandatory | Path, to which the file should be copied |
2022-03-25 21:59:14 +00:00
| `:type` | Keyword, mandatory | `:classpath-resource` or `:host-path` |
2020-06-06 15:30:00 +00:00
2020-09-26 07:59:28 +00:00
#### Result:
2022-03-25 21:59:14 +00:00
2020-06-06 15:30:00 +00:00
The `container-config`
#### Example:
```clojure
2022-03-25 21:59:14 +00:00
(copy-file-to-container! container {:path "test.sql"
2020-06-06 15:30:00 +00:00
:container-path "/opt/test.sql"
2022-03-25 21:59:14 +00:00
:type :host-path})
2020-06-06 15:30:00 +00:00
```
2020-06-06 15:35:43 +00:00
---
2020-06-06 15:30:00 +00:00
### execute-command!
2022-03-25 21:59:14 +00:00
2020-06-06 15:30:00 +00:00
Executes a command in the running container, and returns the result
#### Config parameters:
2020-10-23 21:12:24 +00:00
| Key | Type | Description |
| ------------- | :------------- | :----- |
| First parameter: | | |
| `container-config` | Map, mandatory | Return value of the `create` function |
| Second parameter: | | |
| `command` | Vector with Strings, mandatory | A vector containing the command and its parameters |
2020-06-06 15:30:00 +00:00
2020-09-26 07:59:28 +00:00
#### Result:
2022-03-25 21:59:14 +00:00
2020-10-23 21:12:24 +00:00
| Key | Type | Description |
| ------------- | :------------- | :----- |
| `:exit-code` | int | Exit code of the executed command |
| `:stdout` | String | Content of stdout |
| `:stdin` | String | Content of stdin |
2020-06-06 15:30:00 +00:00
#### Example:
```clojure
(execute-command! container ["tail" "/opt/test.sql"])
```
2020-08-18 12:44:04 +00:00
### create-network
2020-08-05 20:34:49 +00:00
2022-03-25 21:59:14 +00:00
Creates a network. The optional map accepts config values for enabling ipv6 and setting the driver
2020-08-05 20:34:49 +00:00
#### Config parameters:
2020-10-23 21:12:24 +00:00
| Key | Type | Description |
| ------------- | :------------- | :----- |
| `:ipv6` | boolean | Should the network enable IPv6? |
| `:driver` | String | The network driver used by Docker, e.g. `bridge` or `host` |
2020-08-05 20:34:49 +00:00
2020-09-26 07:59:28 +00:00
#### Result:
2022-03-25 21:59:14 +00:00
2020-10-23 21:12:24 +00:00
| Key | Type | Description |
| ------------- | :------------- | :----- |
| `:network` | `org.testcontainers.containers.Network` | The instance of the network |
| `:name` | String | The name of the network |
| `:ipv6` | boolean | Does the network enable IPv6? |
| `:driver` | String | The network driver used |
2020-08-05 20:34:49 +00:00
#### Example:
```clojure
;;Create with config
2022-03-25 21:59:14 +00:00
(create-network {:ipv6 false
2021-06-01 17:52:04 +00:00
:driver "overlay"})
2020-08-05 20:34:49 +00:00
2020-09-26 07:59:28 +00:00
;;Create with default config
(create-network)
2020-08-05 20:34:49 +00:00
```
2020-12-16 09:05:20 +00:00
### perform-cleanup!
2022-03-25 21:59:14 +00:00
Stops and removes all containers which were created in the JVM, including the REPL session you are in. This is helpful,
if you are exploring functionality with containers in the REPL, and create lots of instances on the fly without stopping
them. Testcontainers will remove all containers upon JVM shutdown, but the REPL keeps the JVM alive for a long time.
#### Config parameters:
2020-12-16 09:05:20 +00:00
None
2022-03-25 21:59:14 +00:00
#### Result:
2020-12-16 09:05:20 +00:00
None
#### Example:
2022-03-25 21:59:14 +00:00
2020-12-16 09:05:20 +00:00
```clojure
(perform-cleanup!)
```
2020-10-23 21:12:24 +00:00
### dump-logs
2022-03-25 21:59:14 +00:00
Call on a started container. Provided logging was enabled for a container, returns the given log presentation, e.g. as a
string
2020-12-16 09:06:38 +00:00
| Key | Type | Description |
2020-12-16 09:20:27 +00:00
| ------------- | :------------- | :----- |
2020-10-23 21:12:24 +00:00
| `container-config` | Map, mandatory | The configuration describing the container for which the log should be retrieved |
2020-06-04 08:44:03 +00:00
2020-10-23 21:12:24 +00:00
## License
2022-03-25 21:59:14 +00:00
Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.