Compare commits
4 commits
main
...
release-0.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b2610ee291 | ||
|
|
7d2ff63148 | ||
|
|
0e2d483715 | ||
|
|
3809bbb28c |
9 changed files with 78 additions and 36 deletions
3
.github/workflows/clojure.yml
vendored
3
.github/workflows/clojure.yml
vendored
|
|
@ -6,6 +6,9 @@ on:
|
|||
pull_request:
|
||||
branches: [ main ]
|
||||
|
||||
env:
|
||||
TESTCONTAINERS_REUSE_ENABLE: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
|
|
|
|||
59
README.md
59
README.md
|
|
@ -1,4 +1,4 @@
|
|||
# clj-test-containers
|
||||
# testcontainers-clj
|
||||
|
||||
[](http://clojars.org/clj-test-containers)
|
||||
|
||||
|
|
@ -11,17 +11,13 @@ This library is a lightweight wrapper around the [Testcontainers Java library](h
|
|||
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.
|
||||
|
||||
## Integration with test runners
|
||||
|
||||
There is an [experimental kaocha plugin](https://github.com/lambdaschmiede/kaocha-testcontainers-plugin) you can try out
|
||||
|
||||
## Usage
|
||||
|
||||
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:
|
||||
|
||||
```clojure
|
||||
(require '[clj-test-containers.core :as tc])
|
||||
(require '[testcontainers-clj.core :as tc])
|
||||
|
||||
(def container (-> (tc/create {:image-name "postgres:12.1"
|
||||
:exposed-ports [5432]
|
||||
|
|
@ -41,7 +37,7 @@ If you'd rather create a container from a Dockerfile in your project, it could l
|
|||
|
||||
```clojure
|
||||
|
||||
(require '[clj-test-containers.core :as tc])
|
||||
(require '[testcontainers-clj.core :as tc])
|
||||
|
||||
(def container (-> (tc/create-from-docker-file {:env-vars {"FOO" "bar"}
|
||||
:exposed-ports [80]
|
||||
|
|
@ -52,7 +48,7 @@ If you'd rather create a container from a Dockerfile in your project, it could l
|
|||
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])
|
||||
(require '[testcontainers-clj.core :as tc])
|
||||
(:import [org.testcontainers.containers PostgreSQLContainer])
|
||||
|
||||
(def container (-> (tc/init {:container (PostgreSQLContainer. "postgres:12.2")
|
||||
|
|
@ -72,19 +68,21 @@ Creates a testcontainers instance from a given Docker label and returns them
|
|||
| ------------- | :------------- |:----------------------------------------------------------------------------------------------------|
|
||||
| `: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 |
|
||||
| `:reuse` | Boolean | Should the container be reused, if another Testcontainer with identical config is started? |
|
||||
| `: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 |
|
||||
| `: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} |
|
||||
| `: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} |
|
||||
|
||||
#### Result:
|
||||
|
||||
| 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 |
|
||||
| `:reuse` | Boolean | Is this container reusable? |
|
||||
| `: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 |
|
||||
|
|
@ -103,6 +101,20 @@ Creates a testcontainers instance from a given Docker label and returns them
|
|||
"while true; do echo \"$MAGIC_NUMBER\" | nc -l -p 80; done"]})
|
||||
```
|
||||
|
||||
#### Example with reuse
|
||||
|
||||
```clojure
|
||||
(create {:image-name "alpine:3.2"
|
||||
:exposed-ports [80]
|
||||
:reuse true
|
||||
:env-vars {"MAGIC_NUMBER" "42"}
|
||||
:network (create-network)
|
||||
:network-aliases ["api-server"]
|
||||
:command ["/bin/sh"
|
||||
"-c"
|
||||
"while true; do echo \"$MAGIC_NUMBER\" | nc -l -p 80; done"]})
|
||||
```
|
||||
|
||||
#### Example using wait-for and healthcheck:
|
||||
|
||||
```clojure
|
||||
|
|
@ -123,17 +135,18 @@ Initializes a given Testcontainer, which was e.g. provided by a library
|
|||
|
||||
#### Config parameters:
|
||||
|
||||
| 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 |
|
||||
| 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 |
|
||||
| `:reuse` | Boolean | Should the container be reused, if another Testcontainer with identical config is started? |
|
||||
| `: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 |
|
||||
| `: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} |
|
||||
| | | |
|
||||
| `:log-to` | Map | A map containing the [log strategy](doc/log-strategies.md) to use, e.g. {:log-strategy string} |
|
||||
| | | |
|
||||
|
||||
#### Result:
|
||||
|
||||
|
|
@ -141,6 +154,7 @@ Initializes a given Testcontainer, which was e.g. provided by a library
|
|||
| ------------- | :------------- |:------------------------------------------------------------------------------------------|
|
||||
| `: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 |
|
||||
| `:reuse` | Boolean | Is this container reusable? |
|
||||
| `: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 |
|
||||
|
|
@ -181,6 +195,7 @@ Creates a testcontainer from a Dockerfile
|
|||
| ------------- | :------------- | :----- |
|
||||
| `: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 |
|
||||
| `:reuse` | Boolean | Should the container be reused, if another Testcontainer with identical config is started? |
|
||||
| `: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`) |
|
||||
|
|
@ -195,6 +210,7 @@ Creates a testcontainer from a Dockerfile
|
|||
| ------------- | :------------- | :----- |
|
||||
| `: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 |
|
||||
| `:reuse` | Boolean | Is this container reusable? |
|
||||
| `: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 |
|
||||
|
|
@ -231,6 +247,7 @@ Starts the Testcontainer, which was defined by `create`
|
|||
| ------------- | :------------- | :----- |
|
||||
| `: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 |
|
||||
| `:reuse` | Boolean | Is this container reusable? |
|
||||
| `: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 |
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ The functions accept and return a map structure, which enables us to operate the
|
|||
consistent way. The example shown with Java Interop above would look like this, when using the wrapped functions:
|
||||
|
||||
```clojure
|
||||
(require '[clj-test-containers.core :as tc])
|
||||
(require '[testcontainers-clj.core :as tc])
|
||||
|
||||
(deftest db-integration-test
|
||||
(testing "A simple PostgreSQL integration test"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
(defproject testcontainers-clj "unspecified"
|
||||
(defproject org.testcontainers/testcontainers-clj "unspecified"
|
||||
:description "A lightweight, official wrapper around the Testcontainers Java library"
|
||||
|
||||
:url "https://github.com/testcontainers/testcontainers-clj"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
(ns clj-test-containers.core
|
||||
(ns testcontainers-clj.core
|
||||
(:require
|
||||
[clj-test-containers.spec.core :as cs]
|
||||
[testcontainers-clj.spec.core :as cs]
|
||||
[clojure.spec.alpha :as s]
|
||||
[clojure.string])
|
||||
(:import
|
||||
|
|
@ -183,6 +183,7 @@
|
|||
"Sets the properties for a testcontainer instance"
|
||||
[{:keys [^GenericContainer container
|
||||
exposed-ports
|
||||
reuse
|
||||
env-vars
|
||||
command
|
||||
network
|
||||
|
|
@ -194,6 +195,9 @@
|
|||
(doseq [[k v] env-vars]
|
||||
(.addEnv container k v))
|
||||
|
||||
(when reuse
|
||||
(.withReuse container true))
|
||||
|
||||
(when command
|
||||
(.setCommand container ^"[Ljava.lang.String;" (into-array String command)))
|
||||
|
||||
|
|
@ -425,5 +429,6 @@
|
|||
|
||||
;; REPL Helpers
|
||||
(comment
|
||||
(start! (create {:image-name "postgres:12.1"}))
|
||||
(perform-cleanup!))
|
||||
(start! (create {:image-name "postgres:12.1" :reuse true}))
|
||||
(perform-cleanup!)
|
||||
)
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
(ns clj-test-containers.spec.container
|
||||
(ns testcontainers-clj.spec.container
|
||||
(:require
|
||||
[clojure.spec.alpha :as s]
|
||||
[clojure.spec.gen.alpha :as gen])
|
||||
|
|
@ -14,6 +14,9 @@
|
|||
(s/def ::exposed-ports
|
||||
(s/coll-of (s/int-in 1 65535)))
|
||||
|
||||
(s/def ::reuse
|
||||
boolean?)
|
||||
|
||||
(s/def ::env-vars
|
||||
(s/map-of string? string?))
|
||||
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
(ns clj-test-containers.spec.core
|
||||
(ns testcontainers-clj.spec.core
|
||||
(:require
|
||||
[clj-test-containers.spec.container :as csc]
|
||||
[clj-test-containers.spec.network :as csn]
|
||||
[testcontainers-clj.spec.container :as csc]
|
||||
[testcontainers-clj.spec.network :as csn]
|
||||
[clojure.spec.alpha :as s]))
|
||||
|
||||
(s/def ::wait-for
|
||||
|
|
@ -25,13 +25,15 @@
|
|||
::csc/exposed-ports
|
||||
::csc/env-vars
|
||||
::csc/host]
|
||||
:opt-un [::network
|
||||
:opt-un [::csc/reuse
|
||||
::network
|
||||
::wait-for
|
||||
::log-to]))
|
||||
|
||||
(s/def ::init-options
|
||||
(s/keys :req-un [::csc/container]
|
||||
:opt-un [::csc/exposed-ports
|
||||
::csc/reuse
|
||||
::csc/env-vars
|
||||
::csc/command
|
||||
::network
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
(ns clj-test-containers.spec.network
|
||||
(ns testcontainers-clj.spec.network
|
||||
(:require
|
||||
[clojure.spec.alpha :as s])
|
||||
(:import
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
(ns clj-test-containers.core-test
|
||||
(ns testcontainers-clj.core-test
|
||||
(:require
|
||||
[clj-test-containers.core :as sut]
|
||||
[testcontainers-clj.core :as sut]
|
||||
[clojure.string :refer [includes?]]
|
||||
[clojure.test :refer [deftest is testing]])
|
||||
(:import
|
||||
|
|
@ -115,7 +115,19 @@
|
|||
result (sut/execute-command! initialized-container ["whoami"])
|
||||
_stopped-container (sut/stop! container)]
|
||||
(is (= 0 (:exit-code result)))
|
||||
(is (= "root\n" (:stdout result))))))
|
||||
(is (= "root\n" (:stdout result)))))
|
||||
|
||||
(testing "Reusing a container with the :reuse flag"
|
||||
(let [container-1 (sut/init {:container (PostgreSQLContainer. "postgres:15.3")
|
||||
:exposed-ports [5432]
|
||||
:reuse true})
|
||||
container-2 (sut/init {:container (PostgreSQLContainer. "postgres:15.3")
|
||||
:exposed-ports [5432]
|
||||
:reuse true})
|
||||
initialized-container-1 (sut/start! container-1)
|
||||
initialized-container-2 (sut/start! container-2)]
|
||||
(is (= (.getContainerId (:container initialized-container-1))
|
||||
(.getContainerId (:container initialized-container-2)))))))
|
||||
|
||||
(deftest execute-command-in-container
|
||||
|
||||
Loading…
Reference in a new issue