Liking cljdoc? Tell your friends :D

clj-test-containers

Clojars Project

What it is

This library is a lightweight wrapper around the Testcontainers Java library.

What it isn't

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 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:

(require '[clj-test-containers.core :as tc])

(def container (-> (tc/create {:image-name    "postgres:12.1"
                               :exposed-ports [5432]
                               :env-vars      {"POSTGRES_PASSWORD" "verysecret"}})
                   (tc/bind-filesystem! {:host-path      "/tmp"
                                         :container-path "/opt"
                                         :mode           :read-only})
                   (tc/start!)))

(do-database-testing (:host container)
                     (get (:mapped-ports container) 5432))

(tc/stop! container)

If you'd rather create a container from a Dockerfile in your project, it could look like this:


(require '[clj-test-containers.core :as tc])

(def container (-> (tc/create-from-docker-file {:env-vars      {"FOO" "bar"}
                                                :exposed-ports [80]
                                                :docker-file   "resources/Dockerfile"})
                   (tc/start!)))

If you prefer to use prebuilt containers from the Testcontainers project, you can do it like this

(require '[clj-test-containers.core :as tc])
(:import [org.testcontainers.containers PostgreSQLContainer])

(def container (-> (tc/init {:container     (PostgreSQLContainer. "postgres:12.2")
                             :exposed-ports [5432]})
                   (tc/start!)))

Functions and Properties

create

Creates a testcontainers instance from a given Docker label and returns them

Config parameters:

KeyTypeDescription
:image-nameString, mandatoryThe name and label of an image, e.g. postgres:12.2
:exposed-portsVector with ints, mandatoryAll ports which should be exposed and mapped to a local port
:env-varsMapA map with environment variables
:commandVector with stringsThe start command of the container
:networkMapA map containing the configuration of a Docker Network (see: create-network)
:network-aliasesMapA list of alias names for the container on the network
:wait-forMapA map containing the wait strategy to use and the condition to check for
:log-toMapA map containing the log strategy to use, e.g. {:log-strategy string}

Result:

KeyTypeDescription
:containerorg.testcontainers.containers.ContainerThe Testcontainers instance, accessible for everything this library doesn't provide (yet)
:exposed-portsVector with intsValue of the same input parameter
:env-varsMapValue of the same input parameter
:hostStringThe host for the Docker Container
:networkMapThe network configuration of the Container, if provided
:wait-forMapThe wait-for configuration of the Container, if provided!

Example:

(create {:image-name      "alpine:3.2"
         :exposed-ports   [80]
         :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:

(create {:image-name      "alpine:3.2"
         :exposed-ports   [80]
         :env-vars        {"MAGIC_NUMBER" "42"}
         :network         (create-network)
         :network-aliases ["api-server"]
         :wait-for        {:strategy :health}
         :command         ["/bin/sh"
                           "-c"
                           "while true; do echo \"$MAGIC_NUMBER\" | nc -l -p 80; done"]})

init

Initializes a given Testcontainer, which was e.g. provided by a library

Config parameters:

KeyTypeDescription
:containerorg.testcontainers.containers.GenericContainer, mandatoryThe name and label of an image, e.g. postgres:12.2
:exposed-portsVector with ints, mandatoryAll ports which should be exposed and mapped to a local port
:env-varsMapA map with environment variables
:commandVector with stringsThe start command of the container
:networkMapA map containing the configuration of a Docker Network (see: create-network)
:network-aliasesMapA list of alias names for the container on the network
:wait-forMapA map containing the wait strategy to use and the condition to check for
:log-toMapA map containing the log strategy to use, e.g. {:log-strategy string}

Result:

KeyTypeDescription
:containerorg.testcontainers.containers.ContainerThe Testcontainers instance, accessible for everything this library doesn't provide (yet)
:exposed-portsVector with intsValue of the same input parameter
:env-varsMapValue of the same input parameter
:hostStringThe host for the Docker Container
:networkMapThe network configuration of the Container, if provided
:wait-forMapThe wait-for configuration of the Container, if provided!

Example:

;; PostgreSQL container needs a separate library! This is not included.
(init {:container     (org.testcontainers.containers.PostgreSQLContainer)
       :exposed-ports [80]
       :env-vars      {"MAGIC_NUMBER" "42"}
       :command       ["/bin/sh"
                       "-c"
                       "while true; do echo \"$MAGIC_NUMBER\" | nc -l -p 80; done"]})

Example using wait-for and a log message:

;; PostgreSQL container needs a separate library! This is not included.
(init {:container     (org.testcontainers.containers.PostgreSQLContainer)
       :exposed-ports [80]
       :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"]})

create-from-docker-file

Creates a testcontainer from a Dockerfile

Config parameters:

KeyTypeDescription
:docker-fileString, mandatoryString containing a path to a Dockerfile
:exposed-portsVector with ints, mandatoryAll ports which should be exposed and mapped to a local port
:env-varsMapA map with environment variables
:commandVector with stringsThe start command of the container
:networkMapA map containing the configuration of a Docker Network (see: create-network)
:network-aliasesMapA list of alias names for the container on the network
:wait-forMapA map containing the wait strategy to use and the condition to check for
:log-toMapA map containing the log strategy to use, e.g. {:log-strategy string}

Result:

KeyTypeDescription
:containerorg.testcontainers.containers.ContainerThe Testcontainers instance, accessible for everything this library doesn't provide (yet)
:exposed-portsVector with intsValue of the same input parameter
:env-varsMapValue of the same input parameter
:hostStringThe host for the Docker Container
:networkMapThe network configuration of the Container, if provided
:wait-forMapThe wait-for configuration of the Container, if provided!

Example:

(create-from-docker-file {:docker-file   "resources/Dockerfile"
                          :exposed-ports [5432]
                          :env-vars      {"MAGIC_NUMBER" "42"}
                          :command       ["/bin/sh"
                                          "-c"
                                          "while true; do echo \"$MAGIC_NUMBER\" | nc -l -p 80; done"]})

start!

Starts the Testcontainer, which was defined by create

Config parameters:

KeyTypeDescription
First parameter:
container-configMap, mandatoryReturn value of the create function

Result:

KeyTypeDescription
:containerorg.testcontainers.containers.ContainerThe Testcontainers instance, accessible for everything this library doesn't provide (yet)
:exposed-portsVector with intsValue of the same input parameter
:env-varsMapValue of the same input parameter
:hostStringThe host for the Docker Container
:idStringThe ID of the started docker container
:mapped-portsMapA map containing the container port as key and the mapped local port as a value

Example:

(def container (create {:image-name    "alpine:3.2"
                        :exposed-ports [80]
                        :env-vars      {"MAGIC_NUMBER" "42"}}))

(start! container)

stop!

Stops the Testcontainer, which was defined by create

Config parameters:

KeyTypeDescription
First parameter:
container-configMap, mandatoryReturn value of the create function

Result:

The container-config

Example:

(def container (create {:image-name    "alpine:3.2"
                        :exposed-ports [80]
                        :env-vars      {"MAGIC_NUMBER" "42"}}))

(start! container)
(stop! container)

map-classpath-resource!

Maps a resource from your classpath into the containers file system

Config parameters:

KeyTypeDescription
First parameter:
container-configMap, mandatoryReturn value of the create function
Second parameter:  
:resource-pathString, mandatoryPath of your classpath resource
:container-pathString, mandatoryPath, to which the resource should be mapped
:modeKeyword, mandatory:read-only or :read-write

Result:

The container-config

Example:

(map-classpath-resource! container {:resource-path  "test.sql"
                                    :container-path "/opt/test.sql"
                                    :mode           :read-only})

bind-filesystem!

Binds a path from your local filesystem into the Docker container as a volume

Config parameters:

KeyTypeDescription
First parameter:
container-configMap, mandatoryReturn value of the create function
Second parameter:  
:host-pathString , mandatoryPath on your local filesystem
:container-pathString, mandatoryPath, to which the resource should be mapped
:modeKeyword, mandatory:read-only or :read-write

Result:

The container-config

Example:

(bind-filesystem! container {:host-path      "."
                             :container-path "/opt"
                             :mode           :read-only})

copy-file-to-container!

Copies a file from your filesystem or classpath into the running container

Config parameters:

KeyTypeDescription
First parameter:
container-configMap, mandatoryReturn value of the create function
Second parameter:  
:pathString, mandatoryPath to a classpath resource or file on your filesystem
:host-pathString, mandatoryPath, to which the file should be copied
:typeKeyword, mandatory:classpath-resource or :host-path

Result:

The container-config

Example:

(copy-file-to-container! container {:path           "test.sql"
                                    :container-path "/opt/test.sql"
                                    :type           :host-path})

execute-command!

Executes a command in the running container, and returns the result

Config parameters:

KeyTypeDescription
First parameter:
container-configMap, mandatoryReturn value of the create function
Second parameter:  
commandVector with Strings, mandatoryA vector containing the command and its parameters

Result:

KeyTypeDescription
:exit-codeintExit code of the executed command
:stdoutStringContent of stdout
:stdinStringContent of stdin

Example:

(execute-command! container ["tail" "/opt/test.sql"])

create-network

Creates a network. The optional map accepts config values for enabling ipv6 and setting the driver

Config parameters:

KeyTypeDescription
:ipv6booleanShould the network enable IPv6?
:driverStringThe network driver used by Docker, e.g. bridge or host

Result:

KeyTypeDescription
:networkorg.testcontainers.containers.NetworkThe instance of the network
:nameStringThe name of the network
:ipv6booleanDoes the network enable IPv6?
:driverStringThe network driver used

Example:

;;Create with config
(create-network {:ipv6   false
                 :driver "overlay"})

;;Create with default config
(create-network)

perform-cleanup!

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:

None

Result:

None

Example:

(perform-cleanup!)

dump-logs

Call on a started container. Provided logging was enabled for a container, returns the given log presentation, e.g. as a string

KeyTypeDescription
container-configMap, mandatoryThe configuration describing the container for which the log should be retrieved

License

Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.

Can you improve this documentation? These fine people already did:
Tim Zöller, Burin Choomnuan, Rob Hanlon, Gilles Philippart, David Harrigan & Jakub Holy
Edit on GitHub

cljdoc is a website building & hosting documentation for Clojure/Script libraries

× close