tests: rewrite tests for better maintenance and readability

- Reuse docker_helper.bash script in tests
 - Speed up of tests
 - Better readability
This commit is contained in:
Sameer Naik
2015-11-05 20:24:19 +05:30
parent ce06f8b422
commit 502e972a7a
2 changed files with 243 additions and 58 deletions

View File

@@ -1,100 +1,108 @@
#!/usr/bin/env bats
CONTAINER_NAME=bitnami-redis-test
IMAGE_NAME=bitnami/redis
SLEEP_TIME=3
VOL_PREFIX=/bitnami/redis
REDIS_PASSWORD=test_password123
HOST_VOL_PREFIX=/tmp/$VOL_PREFIX
cleanup_running_containers() {
if [ "$(docker ps -a | grep $CONTAINER_NAME)" ]; then
docker rm -fv $CONTAINER_NAME
fi
# source the helper script
APP_NAME=redis
SLEEP_TIME=15
load tests/docker_helper
# Link to container and execute redis client
# $1 : name of the container to link to
# ${@:2} : arguments for the redis-cli command
redis_client() {
container_link_and_run_command $1 redis-cli -h $APP_NAME "${@:2}"
}
cleanup_volumes_content() {
docker run --rm\
-v $HOST_VOL_PREFIX/data:$VOL_PREFIX/data\
$IMAGE_NAME rm -rf $VOL_PREFIX/data/
}
setup() {
cleanup_running_containers
# Cleans up all running/stopped containers and host mounted volumes
cleanup_environment() {
container_remove_full default
}
# Teardown called at the end of each test
teardown() {
cleanup_running_containers
cleanup_environment
}
create_container(){
docker run -d --name $CONTAINER_NAME "$@" $IMAGE_NAME
sleep $SLEEP_TIME
}
redis_client(){
docker exec $CONTAINER_NAME redis-cli "$@"
}
# cleanup the environment before starting the tests
cleanup_environment
@test "Auth if no password provided" {
create_container
run redis_client ping
container_create default -d
run redis_client default ping
[[ "$output" =~ "PONG" ]]
}
@test "Auth if password provided" {
create_container -e REDIS_PASSWORD=$REDIS_PASSWORD
# Longs sleep because of bnconfig password update
sleep 15
# Can't connect without passw
run redis_client ping
container_create default -d \
-e REDIS_PASSWORD=$REDIS_PASSWORD
run redis_client default ping
[[ "$output" =~ "NOAUTH Authentication required" ]]
run redis_client -a $REDIS_PASSWORD ping
run redis_client default -a $REDIS_PASSWORD ping
[[ "$output" =~ "PONG" ]]
}
@test "Password settings are preserved after restart" {
create_container -e REDIS_PASSWORD=$REDIS_PASSWORD
sleep 15
run docker logs $CONTAINER_NAME
container_create default -d \
-e REDIS_PASSWORD=$REDIS_PASSWORD
run container_logs default
[[ "$output" =~ "Credentials for redis:" ]]
[[ "$output" =~ "Password: $REDIS_PASSWORD" ]]
docker stop $CONTAINER_NAME
docker start $CONTAINER_NAME
sleep $SLEEP_TIME
container_restart default
run docker logs $CONTAINER_NAME
run container_logs default
[[ "$output" =~ "The credentials were set on first boot." ]]
run redis_client -a $REDIS_PASSWORD ping
run redis_client default -a $REDIS_PASSWORD ping
[[ "$output" =~ "PONG" ]]
}
@test "All the volumes exposed" {
create_container
run docker inspect $CONTAINER_NAME
container_create default -d
run container_inspect default --format {{.Mounts}}
[[ "$output" =~ "$VOL_PREFIX/logs" ]]
[[ "$output" =~ "$VOL_PREFIX/conf" ]]
[[ "$output" =~ "$VOL_PREFIX/data" ]]
}
@test "dump.rdb is properly created" {
create_container -v $HOST_VOL_PREFIX/data:$VOL_PREFIX/data
docker stop $CONTAINER_NAME
run docker run -v $HOST_VOL_PREFIX/data:$HOST_VOL_PREFIX/data --rm $IMAGE_NAME ls -l $HOST_VOL_PREFIX/data/dump.rdb
[ $status = 0 ]
cleanup_volumes_content
@test "Data gets generated in conf, data and logs if bind mounted in the host" {
container_create_with_host_volumes default -d
# restart container to force redis-server to generate `dump.rdb`
container_restart default
# files expected in conf volume
run container_exec default ls -la $VOL_PREFIX/conf/
[[ "$output" =~ "redis.conf" ]]
# files expected in data volume
run container_exec default ls -la $VOL_PREFIX/data/
[[ "$output" =~ "dump.rdb" ]]
# files expected in logs volume
run container_exec default ls -la $VOL_PREFIX/logs/
[[ "$output" =~ "redis-server.log" ]]
}
@test "Redis db persists if deleted and host mounted" {
create_container -v $HOST_VOL_PREFIX/data:$VOL_PREFIX/data
run redis_client set winter 'is coming'
@test "If host mounted, configuration and data persist" {
container_create_with_host_volumes default -d \
-e REDIS_PASSWORD=$REDIS_PASSWORD
run redis_client default -a $REDIS_PASSWORD set winter 'is coming'
[[ "$output" =~ "OK" ]]
docker stop $CONTAINER_NAME
docker rm -fv $CONTAINER_NAME
create_container -v $HOST_VOL_PREFIX/data:$VOL_PREFIX/data
run redis_client get winter
# remove container
container_remove default
# recreate container without specifying any env parameters
container_create_with_host_volumes default -d
# check if record exists
run redis_client default -a $REDIS_PASSWORD get winter
[[ "$output" =~ "is coming" ]]
cleanup_volumes_content
}

View File

@@ -0,0 +1,177 @@
#!/bin/bash
##
# Reusable helper script to do docker things in your tests
##
# The following variables should be defined in you BATS script for this helper
# script to work correctly.
#
# APP_NAME - app name, also used as the link alias in container_link_and_run_command
# CONTAINER_NAME - prefix for the name of containers that will be created (default: bitnami-$APP_NAME-test)
# IMAGE_NAME - the docker image name (default: bitnami/$APP_NAME)
# SLEEP_TIME - time in seconds to wait for containers to start (default: 5)
# VOL_PREFIX - prefix of volumes inside the container (default: /bitnami/$APP_NAME)
# VOLUMES - colon separated list of container volumes (default: $VOL_PREFIX/data:$VOL_PREFIX/conf:$VOL_PREFIX/logs)
# HOST_VOL_PREFIX - prefix of volumes mounted from the host (default: /tmp/bitnami/$CONTAINER_NAME)
# container_link_and_run_command_DOCKER_ARGS - optional arguments passed to docker run in container_link_and_run_command (default: none)
##
CONTAINER_NAME=bitnami-$APP_NAME-test
IMAGE_NAME=${IMAGE_NAME:-bitnami/$APP_NAME}
SLEEP_TIME=${SLEEP_TIME:-5}
VOL_PREFIX=${VOL_PREFIX:-/bitnami/$APP_NAME}
VOLUMES=${VOLUMES:-$VOL_PREFIX/data:$VOL_PREFIX/conf:$VOL_PREFIX/logs}
HOST_VOL_PREFIX=${HOST_VOL_PREFIX:-/tmp/bitnami/$CONTAINER_NAME}
# Creates a container whose name has the prefix $CONTAINER_NAME
# $1: name for the new container
# ${@:2}: additional arguments for docker run while starting the container
container_create() {
docker run --name $CONTAINER_NAME-$1 "${@:2}" $IMAGE_NAME
sleep $SLEEP_TIME
}
# Creates a container with host mounted volumes for volumes listed in VOLUMES
# $1: name for the new container
# ${@:2}: additional arguments for docker run while starting the container
container_create_with_host_volumes() {
# populate volume mount arguments from VOLUMES variable
VOLUME_ARGS=
OLD_IFS=${IFS}
IFS=":"
for VOLUME in $VOLUMES
do
VOL_NAME=$(basename $VOLUME)
VOLUME_ARGS+="-v $HOST_VOL_PREFIX/$1/$VOL_NAME:$VOLUME "
done
IFS=${OLD_IFS}
container_create $1 "${@:2}" $VOLUME_ARGS
}
# Start a stopped container
# $1: name of the container
container_start() {
if docker ps -a | grep -q $CONTAINER_NAME-$1; then
docker start $CONTAINER_NAME-$1
sleep $SLEEP_TIME
else
return 1
fi
}
# Stop a running container
# $1: name of the container
container_stop() {
if docker ps | grep -q $CONTAINER_NAME-$1; then
docker stop $CONTAINER_NAME-$1
else
return 1
fi
}
# Restart a running container (stops the container and then starts it)
# $1: name of the container
container_restart() {
if docker ps | grep -q $CONTAINER_NAME-$1; then
docker stop $CONTAINER_NAME-$1
docker start $CONTAINER_NAME-$1
sleep $SLEEP_TIME
fi
}
# Remove a running/stopped container
# $1: name of the container
container_remove() {
if docker ps -a | grep -q $CONTAINER_NAME-$1; then
docker stop $CONTAINER_NAME-$1
docker rm -v $CONTAINER_NAME-$1
fi
}
# Remove a running/stopped container and clear host volumes
# $1: name of the container
container_remove_full() {
container_remove $1
# populate volume mount and rm arguments from VOLUMES variable
VOLUME_ARGS=
RM_ARGS=
OLD_IFS=${IFS}
IFS=":"
for VOLUME in $VOLUMES
do
VOL_NAME=$(basename $VOLUME)
VOLUME_ARGS+="-v $HOST_VOL_PREFIX/$1/$VOL_NAME:$VOLUME "
RM_ARGS+="$VOLUME/* $VOLUME/.[^.]* "
done
IFS=${OLD_IFS}
docker run --rm --entrypoint bash $VOLUME_ARGS \
$IMAGE_NAME -c "rm -rf $RM_ARGS"
}
# Get the logs of a container
# $1: name of the container
container_logs() {
if docker ps -a | grep -q $CONTAINER_NAME-$1; then
docker logs $CONTAINER_NAME-$1
else
return 1
fi
}
# Docker inspect a container
# $1: name of the container
container_inspect() {
if docker ps -a | grep -q $CONTAINER_NAME-$1; then
# docker inspect "${@:2}" $CONTAINER_NAME-$1 # requires docker >= 1.9.0
docker inspect $CONTAINER_NAME-$1
else
return 1
fi
}
# Execute a command in a running container using docker exec
# $1: name of the container
container_exec() {
if docker ps | grep -q $CONTAINER_NAME-$1; then
docker exec $CONTAINER_NAME-$1 "${@:2}"
else
return 1
fi
}
# Execute a command in a running container using docker exec (detached)
# $1: name of the container
container_exec_detached() {
if docker ps | grep -q $CONTAINER_NAME-$1; then
docker exec -d $CONTAINER_NAME-$1 "${@:2}"
else
return 1
fi
}
# Generates docker link parameter for linking to a container
# $1: name of the container to link
# $2: alias for the link
container_link() {
if docker ps -a | grep -q $CONTAINER_NAME-$1; then
echo "--link $CONTAINER_NAME-$1:$2"
fi
}
# Link to container and execute command
# $1: name of the container to link to
# ${@:2}: command to execute
container_link_and_run_command() {
# launch command as the entrypoint to skip the s6 init sequence (speeds up the tests)
docker run --rm $(container_link $1 $APP_NAME) $container_link_and_run_command_DOCKER_ARGS --entrypoint ${2} $IMAGE_NAME "${@:3}"
}
# Link to container and execute curl
# $1: name of the container to link to
# ${@:2}: arguments to curl
curl_client() {
container_link_and_run_command $1 curl --noproxy $APP_NAME --retry 5 -L "${@:2}"
}