Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/testcontainers/testcontainers-hs

Docker containers for your integration tests! http://hackage.haskell.org/package/testcontainers
https://github.com/testcontainers/testcontainers-hs

Last synced: 2 months ago
JSON representation

Docker containers for your integration tests! http://hackage.haskell.org/package/testcontainers

Awesome Lists containing this project

README

        

# About

Testcontainers is a Haskell library that provides a friendly API to run Docker
containers. It is designed to create a runtime environment to use during your
integration tests

# Example

``` haskell
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
module Main where

import qualified Test.Tasty as Tasty
import qualified Test.Tasty.HUnit as Tasty
import qualified TestContainers.Tasty as TC

data Endpoints = Endpoints
{
redisHost :: String
, redisPort :: Int
}

-- | Sets up and runs the containers required for this test suite.
setupContainers :: TC.MonadDocker m => m Endpoints
setupContainers = do

-- Launch the container based on the redis:5.0.0 image.
redisContainer <- TC.run $ TC.containerRequest (TC.fromTag "redis:5.0.0")
-- Expose the port 6379 from within the container. The respective port
-- on the host machine can be looked up using `containerPort` (see below).
TC.& TC.setExpose [ 6379 ]
-- Wait until the container is ready to accept requests. `run` blocks until
-- readiness can be established.
TC.& TC.setWaitingFor (TC.waitUntilMappedPortReachable 6379)

pure $ Endpoints
{
redisHost = "0.0.0.0"
, redisPort =
-- Look up the corresponding port on the host machine for the exposed
-- port 6379.
TC.containerPort redisContainer 6379
}

main :: IO ()
main =
Tasty.defaultMain $
-- Use `withContainers` to make the containers available in the closed over
-- tests. Due to how Tasty handles resources `withContainers` passes down
-- an IO action `start` to actually start up the containers. `start` can be
-- invoked multiple times, Tasty makes sure to only start up the containrs
-- once.
--
-- `withContainers` ensures the started containers are shut down correctly
-- once execution leaves its scope.
TC.withContainers setupContainers $ \start ->
Tasty.testGroup "Some test group"
[
Tasty.testCase "Redis test" $ do
-- Actually start the containers!!
Endpoints {..} <- start
-- ... assert some properties
pure ()

, Tasty.testCase "Another Redis test" $ do
-- Invoking `start` twice gives the same Endpoints!
Endpoints {..} <- start
-- ... assert some properties
pure ()
]
```