Crate dockertest

source ·
Expand description

dockertest is a testing and automation abstraction for Docker.

This testing library enables control and lifecycle management with docker containers from an integration test, taking full care of start and cleanup phases. Containers can be backed by various container registries, even behind authentication barrier.

The main entrypoint to construct and a run a dockertest powered integration test starts with DockerTest.

The underlying docker engine to use can be configured through:

  • UNIX domain socket (linux)
  • Named pipes (windows)
  • TCP with TLS
  • Piped through a docker-in-docker container where the execution occurs, to run on the underlying docker engine.

The main bread-and-butter of this library is the ability to specify which containers are required for a test, and how one should ensure that the container is properly running prior to starting the actual test body. Furthermore, dockertest supports interacting with existing containers, without interfering with its lifecycle management.

Lifecycle management

There are multiple ways to control and interact with containers, with various trade-offs.

Full isolation - TestBodySpecification

The container is created, started, and cleaned up entirely within a single test body. This is the highest level of isolation, and no other tests can interfere with this container. The main drawback of this method is the high wall-time needed to start these containers. If there are many integration tests in this mode, the total test run-time will be made primarily by the container management overhead.

Externally managed - ExternalSpecification

The container is never touched by dockertest. It is assumed to be started by some external entity, and the container is never teared down by dockertest. Prior to running the test body, the existence of the external container is verified.

Conditionally managed - DynamicSpecification

The containers lifecycle is only managed for creation, but not deletion. When multiple specifications relate to the same underlying container, dockertest will attempt to locate an existing container, and reuse this container to fulfill the specification. Once the test body exists, the container will be left running.

This mode is useful in when there are multiple tests, over a long period of development time, that can utilize the same underlying container without causing cross-test contamination. This will lead to significantly faster test execution time.

WaitFor - determining when a container is ready

Each container that dockertest creates and starts must also have a policy to detect when the container it has started is actually ready to start serving the test body. This is achived through a trait object WaitFor, where an implementation can be provided outside of dockertest.

The batteries included implementations are:

  • RunningWait - wait for the container to report running status.
  • ExitedWait - wait for the container to report exited status.
  • NoWait - don’t wait for anything
  • MessageWait - wait for the following message to appear in the log stream.

Environment variables

The following set of environment variables can impact running tests utilizing dockertest.

Prune policy

By default, dockertest will stop and remove all containers and created volumes regardless of execution result. You can control this policy by setting the environment variable DOCKERTEST_PRUNE:

  • always: default remove everything
  • never: leave all containers running
  • stop_on_failure: stop containers on execution failure
  • running_on_failure: leave containers running on execution failure

Dockertest in Docker

If the execution environment of running dockertest is itself a docker-in-docker container, one may have connectivity issues between the test body code, and the container dependencies. To ensure connectivity, dockertest must be instructed about the name/identifier of the execution container to include it into the docker network of the test containers. This is usually because the docker-in-docker docker daemon connection is routed to the underlying host itself.

DOCKERTEST_CONTAINER_ID_INJECT_TO_NETWORK=your_container_id/name

Example


use dockertest::{TestBodySpecification, DockerTest};
use std::sync::{Arc, Mutex};

#[test]
fn hello_world_test() {
    // Define our test instance
    let mut test = DockerTest::new();

    // A container specification can have multiple properties, depending on how the
    // lifecycle management of the container should be handled by dockertest.
    //
    // For any container specification where dockertest needs to create and start the container,
    // we must provide enough information to construct a composition of
    // an Image configured with provided environment variables, arguments, StartPolicy, etc.
    let hello = TestBodySpecification::with_repository("hello-world");

    // Populate the test instance.
    // The order of compositions added reflect the execution order (depending on StartPolicy).
    test.provide_container(hello);

    let has_ran: Arc<Mutex<bool>> = Arc::new(Mutex::new(false));
    let has_ran_test = has_ran.clone();
    test.run(|ops| async move {
        // A handle to operate on the Container.
        let _container = ops.handle("hello-world");

        // The container is in a running state at this point.
        // Depending on the Image, it may exit on its own (like this hello-world image)
        let mut ran = has_ran_test.lock().unwrap();
        *ran = true;
    });

    let ran = has_ran.lock().unwrap();
    assert!(*ran);
}

Modules

  • Contains WaitFor trait used to determine when a PendingContainer has started and all the default implementations of it.

Structs

  • The test body parameter provided in the DockerTest::run argument closure.
  • The main entry point to specify a test.
  • A full specification of a container whose lifecycle is partially managed by dockertest.
  • A specification of a container external to dockertest.
  • Represents a docker Image.
  • Specifies how dockertest should handle logging output from this specific container.
  • Represent a docker container object in a pending phase between it being created on the daemon, but may not be running.
  • Represents credentials to a custom remote Docker Registry.
  • Represent a docker container in running state and available to the test body.
  • The standard container specification.
  • A specification of a container that shall live across all tests within the testsuite, and should be appropriately shut down once all tests in the suite have terminated.

Enums

  • Public library error conditions.
  • Specifies how should dockertest should handle log output from this container.
  • Specifies when LogAction is applicable.
  • Specifies which log sources we want to read from containers.
  • Configure how the docker network should be applied to the containers within this test.
  • The policy for pulling from remote locations.
  • Represents the Source of an Image.
  • Specifies the starting policy of a container specification.

Traits

  • Implemented by types that can represent and instruct how dockertest should interact with a specific docker container.