Dockerspec
A small Ruby Gem to run RSpec, Serverspec, Infrataster and Capybara tests against Dockerfiles or Docker images easily.
This gem is designed to work out of the box on Travis CI, CircleCI and other similar CI environments.
Table of Contents
- Requirements
- Installation
- Documentation
- Presentations
- Usage Examples
- Run Tests Against a Dockerfile in the Current Directory
- Run Tests Against Docker Compose
- Checking Container Logs
- Retrying Tests That Fail Temporarily
- Run HTTP Tests Using Infrataster
- Run HTTP Tests Using Capybara
- Run Database Tests Using
infrataster-plugin-mysql
Gem with Docker Compose - Run Different Tests on Each Platform
- Real-world Examples
- Prepare Your Ruby Environment
- Travis CI Configuration Example
- CircleCI Configuration Example
- Testing
- Contributing
- TODO
- License and Author
Requirements
- Ruby
2.2
or higher. - Recommended Docker
1.7
or higher.
Installation
You can install the Ruby Gem with:
$ gem install dockerspec
Or you can add this line to the Gemfile of your application:
gem 'dockerspec', '~> 0.5.0'
And then execute:
$ bundle
Warning: As the gem is in its early development stages, the API is very likely to break between minor versions.
Documentation
- Latest release documentation: http://www.rubydoc.info/gems/dockerspec
- Master unreleased documentation: http://www.rubydoc.info/github/zuazo/dockerspec
Specific documentation sections for resources or functions that can be used to generate test cases:
Presentations
Apart from the official documentation, Nan Liu presented a talk for Portland Docker user group regarding how to use Dockerspec in a container:
Usage Examples
Run Tests Against a Dockerfile in the Current Directory
require 'dockerspec/serverspec'
describe 'My Dockerfile' do
describe docker_build('.') do
it { should have_maintainer /John Doe/ }
it { should have_cmd ['/bin/dash'] }
it { should have_expose '80' }
it { should have_user 'nobody' }
describe docker_run(described_image) do
describe file('/etc/httpd.conf') do
it { should be_file }
it { should contain 'ServerName www.example.jp' }
end
describe service('httpd') do
it { should be_enabled }
it { should be_running }
end
end
end
end
See the documentation above for more examples.
Run Tests Against Docker Compose
require 'dockerspec/serverspec'
describe docker_compose('.', wait: 30) do
its_container(:myapp) do
describe process('apache2') do
it { should be_running }
its(:args) { should match(/-DFOREGROUND/) }
end
# [...]
end
its_container(:db) do
its(:stdout) { should include 'MySQL init process done.' }
describe process('mysqld') do
it { should be_running }
end
# [...]
end
end
Important Warning: The docker_compose
resource uses the docker-compose-api
Ruby gem to emulate Docker Compose. So, some docker-compose.yml configuration options may not be supported yet or may not work exactly the same. Let us know if you find any bug or you need a missing feature. And thanks to Mauricio Klein for all his work by the way!
Checking Container Logs
To check the running container logs content, you can use the stdout
and stderr
helpers inside docker_run
or its_container
blocks.
For example:
require 'dockerspec/serverspec'
describe 'My Dockerfile' do
describe docker_build('.') do
describe docker_run(described_image) do
its(:stdout) { should include 'Successfully Started.' }
its(:stderr) { should eq '' }
end
end
end
Retrying Tests That Fail Temporarily
This gem includes the rspec-retry
gem. So, you can add :retry
to the RSpec metadata in order to retry some tests multiple times.
For example:
describe docker_run('mariadb') do
its(:stdout, retry: 30) { should include 'MySQL init process done.' }
end
By default, it will do a sleep of 1 second between each retry. You can adjust it with :retry_wait
. See rspec-retry
documentation for more details.
You can also make all tests within a block retry:
describe docker_run('mariadb'), retry: 30 do
its(:stdout) { should include 'MySQL init process done.' }
its(:stderr) { should include 'MySQL init process done.' }
describe command('mysqld -V'), retry: 1 do # disable retries here
its(:stdout) { should match(/^mysqld .*MariaDB/i) }
end
end
The same applies to its_container
blocks.
Run HTTP Tests Using Infrataster
# require 'dockerspec/serverspec' # Only if you want to run both types of tests
require 'dockerspec/infrataster'
describe docker_run('nginx') do
describe server(described_container) do # Infrataster
describe http('/') do
it 'responds content including "Welcome to nginx!"' do
expect(response.body).to include 'Welcome to nginx!'
end
it 'responds as "nginx" server' do
expect(response.headers['server']).to match(/nginx/i)
end
end
end
end
See the Infrataster Resources documentation for more information.
Run HTTP Tests Using Capybara
In the following example we set the admin password and log in in a hypothetical web application:
require 'dockerspec/infrataster'
describe docker_build('.', tag: 'mywebapp') do
describe docker_run('mywebapp') do
describe server(described_container) do
describe capybara('/') do
let(:password) { '4dm1nP4ssw0rd' }
describe 'on /setup' do
before { visit '/setup' }
it 'contains "Configure the password"' do
expect(page).to have_content 'Configure the password'
end
it 'sets the admin password' do
fill_in 'Password', with: password
fill_in 'Confirm Password', with: password
click_button 'Set password'
end
end
describe 'on /login' do
before { visit '/login' }
it 'logs in as admin' do
expect(page).to have_content 'sign in'
fill_in 'User name', with: 'admin'
fill_in 'Password', with: password
click_button 'Sig in'
end
end
describe 'on /' do
before { visit '/' }
it 'is logged id' do
expect(page).to have_content 'Welcome admin!'
end
end
end
end
end
end
See the Capybara DSL documentation for more information.
Run Database Tests Using infrataster-plugin-mysql
Gem with Docker Compose
You need to include the infrataster-plugin-mysql
gem in your Gemfile:
# Gemfile
# gem [...]
gem 'infrataster-plugin-mysql', '~> 0.2.0'
A docker-compose.yml file example with a database:
myapp:
image: myapp
links:
- db:mysql
ports:
- 8080:80
db:
image: mariadb
environment:
- MYSQL_ROOT_PASSWORD=example
The file with the tests:
require 'dockerspec/infrataster'
require 'infrataster-plugin-mysql'
describe docker_compose('docker-compose.yml', wait: 60) do
its_container(:db, mysql: { user: 'root', password: 'example' }) do
describe server(described_container) do # Infrataster
describe mysql_query('SHOW STATUS') do
it 'returns positive uptime' do
row = results.find { |r| r['Variable_name'] == 'Uptime' }
expect(row['Value'].to_i).to be > 0
end
end
describe mysql_query('SHOW DATABASES') do
it 'includes `myapp` database' do
databases = results.map { |r| r['Database'] }
expect(databases).to include('myapp')
end
end
end
end
end
Run Different Tests on Each Platform
Sometimes, you may want to be able to run different tests depending on the platform. You can use Serverspec's os
helper method for that:
require 'dockerspec/serverspec'
describe docker_build('.', tag: 'mywebapp') do
describe docker_run('mywebapp') do
case os[:family]
when 'debian'
describe file('/etc/debian_version') do
it { should exist }
end
# [...]
when 'alpine'
describe file('/etc/alpine-release') do
it { should exist }
end
# [...]
end
end
end
For more details, see Serverspec documenation on how to get OS information.
Real-world Examples
-
alpine-tor
image (spec/, Gemfile, .travis.yml). -
chef-local
image (spec/, Gemfile, .travis.yml): Runs the same tests against multiple tags. -
keywhiz
image (spec/, Gemfile, .travis.yml). -
irssi-tor
image (spec/, Gemfile, .travis.yml). -
dradis
image (spec/, Gemfile, .travis.yml): Runs some Capybara HTTP tests.
Prepare Your Ruby Environment
If you are new to Ruby, you can follow these steps:
1. Create a Gemfile:
# Gemfile
source 'https://rubygems.org'
gem 'dockerspec', '~> 0.5.0'
2. Create the spec/ directory:
$ mkdir spec
3. Add your tests to a file with the spec/myapp_spec.rb format:
With this gem, you can use both Serverspec and Infrataster tests.
If you just want to use Serverspec tests:
require 'dockerspec/serverspec'
If you just want to use Infrataster tests:
require 'dockerspec/infrataster'
But, of course, you can use both types of tests if you want:
require 'dockerspec/serverspec'
require 'dockerspec/infrataster'
For example, you can create a file in spec/myapp_spec.rb with the following content:
# spec/myapp_spec.rb
require 'dockerspec/serverspec'
describe 'My Dockerfile' do
describe docker_build('.') do
# [...]
describe docker_run(described_image) do
# [...]
end
end
end
4. Install the gems:
$ bundle
5. Run the tests:
$ bundle exec rspec
Travis CI Configuration Example
.travis.yml file example:
language: ruby
sudo: required
services: docker
script: travis_retry bundle exec rspec
CircleCI Configuration Example
circle.yml file example:
machine:
services:
- docker
ruby:
version: 2.2.3
test:
override:
- bundle exec rspec
Testing
See TESTING.md.
Contributing
Please do not hesitate to open an issue with any questions or problems.
See CONTRIBUTING.md.
TODO
See TODO.md.
License and Author
Author: | Xabier de Zuazo (xabier@zuazo.org) |
Contributor: | John Meichle |
Copyright: | Copyright (c) 2015-2016 Xabier de Zuazo |
License: | Apache License, Version 2.0 |
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.