cntest

package module
v1.2.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 18, 2023 License: MIT Imports: 20 Imported by: 0

README

cntest

Go Report Card Go Doc Release

Docker container-based testing and db container testing made easy.

Background

CnTest Tries to take most of the boilerplate away in creating containers. Typically you would have a combination of scripts and code to start a container and then wait for it to start, or run to completion or reach a point where it logs something, before running a test.

CnTest allows you to do all of that within the context of a go test. This includes cleaning up after itself so you dont have a bunch of zombie containers left around. It also uses random identifiers for things like dbnames and usernames so you don't have to manually configure them, and also this means that you can spin up multiple db hosts for example to test against.

Usage

// from examples/mysql_test.go

  func TestMysqlRunWith(t *testing.T) {

	// This sets up a mysql db server with all the bits randomised
	// you can access them via cnt.Props map. see mysql.Container() method for details.
	cnt := mysql.Container(cntest.PropertyMap{"initdb_path": "../path/to/folder/containing/your/init/sql"})

	// This wrapper method ensures the container is cleaned up after the test is done
	cntest.ExecuteWithRunningContainer(t, cnt, func(t *testing.T, c *cntest.Container) {

		// Open up our database connection.
		db, err := c.DBConnect(c.MaxStartTimeSeconds)
		// if err...
		defer db.Close()

		// example ping to check connection
		err = db.Ping()
		// if err...

		// Use sql.db in your tests 

	})

See more examples/ for examples of tests for

  • a hello world container
  • a mysql db
  • a postgres db

Documentation

Index

Constants

View Source
const NOPORT = HostPort("")

NOPORT constant for no port specified

Variables

This section is empty.

Functions

func API

func API() *client.Client

API returns current API client or creates on first call

func ExecuteWithRunningContainer

func ExecuteWithRunningContainer(t *testing.T, c *Container, userTestFn ContainerTestFn)

ExecuteWithRunningContainer wraps a test function by creating a db

func FromDockerHub

func FromDockerHub(image string, version string) string

FromDockerHub is the default formatter for a docker image resource provide your own for private repos

func PullImage

func PullImage(image string, version string, getRepoFn ImageRefFn)

PullImage like docker pull cmd

Types

type Container

type Container struct {

	// Props are metadata for a container type. eg dbusername for a db container
	// They are not passed directly to the container environment
	Props PropertyMap

	// These two are used to create the new container using the Docker API
	Config     *container.Config
	HostConfig *container.HostConfig

	// Instance Once the container is started this has all the instance data
	Instance container.CreateResponse

	// GetImageRepoSource Overload this if you want to get images from a different repo
	GetImageRepoSource ImageRefFn `json:"-,"`

	// will stop and remove the container after testing
	StopAfterTest bool
	// RemoveAfterTest remove the container after the test
	RemoveAfterTest bool

	// The Maximum time to wait for the container
	MaxStartTimeSeconds int

	// NamePrefix is combined with a random suffix to create the containerName
	// if the name is blank when the container is started
	NamePrefix string

	// ContainerReady Override this if you want to check more than an ok response to a TCP connect
	ContainerReady ContainerReadyFn `json:"-,"`

	// TCPConnect fn to connect to a TCP connection
	TCPConnect TCPConnectFn `json:"-,"`

	// DBConnect fn to connect to a DB connection
	DBConnect DBConnectFn `json:"-,"`
	// contains filtered or unexported fields
}

Container a simplified API over the docker client API

func ContainerWith

func ContainerWith(fn ContainerConfigFn) *Container

ContainerWith contstructor which takes a custom configurer

func NewContainer

func NewContainer() *Container

NewContainer constructor fn

func (*Container) AddAllEnv

func (c *Container) AddAllEnv(aMap map[string]string)

AddAllEnv adds the mapped values to the config

func (*Container) AddEnv

func (c *Container) AddEnv(key, value string)

AddEnv adds the value to the config

func (*Container) AddExposedPort

func (c *Container) AddExposedPort(port ContainerPort)

AddExposedPort expose a container port

func (*Container) AddPathMap

func (c *Container) AddPathMap(Host HostPath, Container ContainerPath)

AddPathMap like -v cmd switch for mapping paths

func (*Container) AddPortMap

func (c *Container) AddPortMap(host HostPort, container ContainerPort)

AddPortMap like -p cmd line switch for adding port mappings

func (*Container) AwaitExit

func (c *Container) AwaitExit(timeoutSeconds int) (ok bool, err error)

AwaitExit waits for the container to stop

func (*Container) AwaitIsReady

func (c *Container) AwaitIsReady() (started bool, err error)

AwaitIsReady waits for the container is in the running state

func (*Container) AwaitIsRunning

func (c *Container) AwaitIsRunning() (started bool, err error)

AwaitIsRunning waits for the container is in the running state

func (*Container) AwaitLogPattern

func (c *Container) AwaitLogPattern(timeoutSeconds int, patternRegex string) (started bool, err error)

AwaitLogPattern waits for the container to start based on expected log message patterns

func (*Container) Check

func (c *Container) Check(timeoutSeconds int) (ret bool, err error)

Check if tcp port is open

func (*Container) ConnectTCP

func (c *Container) ConnectTCP(timeoutSeconds int) (net.Conn, error)

ConnectTCP Connects tot he container port using a TCP connection

func (*Container) ContainerName

func (c *Container) ContainerName() string

ContainerName returns the generated name for the container

func (*Container) HostPort

func (c *Container) HostPort() string

HostPort get the host port

func (*Container) IPAddress

func (c *Container) IPAddress() (string, error)

IPAddress retrieve the IP address of the running container

func (*Container) InspectIPAddress

func (c *Container) InspectIPAddress() (string, error)

InspectIPAddress uses docker inspect to find out the ip address

func (*Container) IsExited

func (c *Container) IsExited() (started bool, err error)

IsExited returns true if the container has exited

func (*Container) IsRemoveAfterTest

func (c *Container) IsRemoveAfterTest() bool

IsRemoveAfterTest true if the container should be removed

func (*Container) IsRunning

func (c *Container) IsRunning() (started bool, err error)

IsRunning returns true if the container is in the started state Will error if the container has already exited

func (*Container) IsStopAfterTest

func (c *Container) IsStopAfterTest() bool

IsStopAfterTest if true then stop the container after the test

func (*Container) Logs

func (c *Container) Logs() (string, error)

Logs returns the container logs as a string or error

func (*Container) LogsMatch

func (c *Container) LogsMatch(pattern string) func() (bool, error)

LogsMatch returns a fn matcher for bool wait fns

func (*Container) MapToRandomHostPort

func (c *Container) MapToRandomHostPort(containerPort ContainerPort)

MapToRandomHostPort like --ports cmd switch for mapping ports

func (*Container) Port

func (c *Container) Port() ContainerPort

Port returns the containers port

func (*Container) Remove

func (c *Container) Remove() error

Remove deletes the container permanently

func (*Container) RunCmd

func (c *Container) RunCmd(cmd []string) (io.Reader, error)

RunCmd execs the specified command and args on the container

func (*Container) SetAppPort

func (c *Container) SetAppPort(port string) *Container

SetAppPort sets the main port for the container if it has one

func (*Container) SetName

func (c *Container) SetName(name string)

SetName container name

func (*Container) SetPort

func (c *Container) SetPort(port string, mappedHostPort string) *Container

SetPort sets the main port to be used by the container Other port mappings can be added but this one is considered the big kahuna for checking readiness for example

func (*Container) Start

func (c *Container) Start() (string, error)

Start starts the container

func (*Container) Stop

func (c *Container) Stop(timeoutSeconds int) (ok bool, err error)

Stop stops the container

func (*Container) WithImage

func (c *Container) WithImage(image string) *Container

WithImage sets the image name and the default container name prefix

type ContainerConfigFn

type ContainerConfigFn func(c *Container) error

ContainerConfigFn custom function that configures a container

type ContainerGroup

type ContainerGroup map[string]*GroupedContainer

ContainerGroup manages a group of connected containers like docker-compose but in code

func (ContainerGroup) Add

func (cg ContainerGroup) Add(cnt *GroupedContainer)

Add adds a container to the group keyed by its name

func (ContainerGroup) Await

func (cg ContainerGroup) Await()

Await blocks until all containers have started

func (ContainerGroup) Start

func (cg ContainerGroup) Start()

Start starts all the containers

type ContainerPath

type ContainerPath string

ContainerPath typesafe string subtype

type ContainerPort

type ContainerPort string

ContainerPort typesafe string subtype

func (ContainerPort) Nat

func (p ContainerPort) Nat() nat.Port

Nat does the string formatting for a nat port

type ContainerReadyFn

type ContainerReadyFn func() (bool, error)

ContainerReadyFn should return true when the container is ready to be used

type ContainerTestFn

type ContainerTestFn func(t *testing.T)

ContainerTestFn implement your DB tests using this signature

type DBConnectFn

type DBConnectFn = func(timeoutSeconds int) (*sql.DB, error)

DBConnectFn override this to provide a DB connect function

type GroupedContainer

type GroupedContainer struct {
	Container *Container
	// contains filtered or unexported fields
}

GroupedContainer container object tracks containers on which this depends

func NewGroupedContainer

func NewGroupedContainer(withContainer *Container) *GroupedContainer

NewGroupedContainer constructor with a container

func (*GroupedContainer) Await

func (gc *GroupedContainer) Await()

Await uses a for range on a channel to wait for all dependent containers to start

func (*GroupedContainer) DependsOn

func (gc *GroupedContainer) DependsOn(containers ...*GroupedContainer)

DependsOn is called to ensure this container wont start until these ones have

func (*GroupedContainer) SignalStarted

func (gc *GroupedContainer) SignalStarted()

SignalStarted signals

func (*GroupedContainer) Start

func (gc *GroupedContainer) Start()

Start starts a container once all the dependents start

type HostPath

type HostPath string

HostPath typesafe string subtype

type HostPort

type HostPort string

HostPort typesafe string subtype

func (HostPort) Binding

func (p HostPort) Binding() nat.PortBinding

Binding Returns a host binding and optionally creates a random one if none provided

type ImageRefFn

type ImageRefFn func(image string, version string) string

ImageRefFn This function type provides a hook to generate a custom docker repo path if needed You only need this if you're not using the standard docker registry

type PortMap

type PortMap struct {
	Host      HostPort
	Container ContainerPort
}

PortMap defines a host to container port mapping

func (PortMap) AddTo

func (p PortMap) AddTo(portmap nat.PortMap)

AddTo adds this mapping to a docker Portmap map

type PropertyMap

type PropertyMap map[string]string

PropertyMap Custom container properties used to configure containers They are stored here for later reference eg by tests eg They could include db username/password for a db type container

func (PropertyMap) GetOrDefault

func (p PropertyMap) GetOrDefault(key string, defaultValue string) string

GetOrDefault returns the specified key value or a default

func (PropertyMap) SetAll

func (p PropertyMap) SetAll(amap PropertyMap)

SetAll sets all the props on the provided map

func (PropertyMap) SetIfMissing

func (p PropertyMap) SetIfMissing(key string, value string)

SetIfMissing sets the value if it isn't already

type TCPConnectFn

type TCPConnectFn = func(timeoutSeconds int) (net.Conn, error)

TCPConnectFn override this to provide a tcp connect function

type VolumeMount

type VolumeMount struct {
	Host      HostPath
	Container ContainerPath
}

VolumeMount creates a Volume mount from host to container

func (*VolumeMount) Mount

func (v *VolumeMount) Mount() mount.Mount

Mount is a converter to a docker api mount struct

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL