I have 2 spec files that use different docker images and therefore are suppose to start separate and different docker containers to run the examples.
In the snippets below I'm using the serverspec
gem to test my containers
require 'spec_helper'
require 'shared_examples/release'
describe 'ember' do
before(:all) do
@image = Docker::Image.build_from_dir(image_path('ember'))
set :os, family: :alpine
set :backend, :docker
set :docker_image, @image.id
set :docker_container_create_options, { 'Entrypoint' => ['/bin/sh'] }
end
describe command('ember version') do
its(:stdout) { should contain 'ember-cli: 3.3.0' }
its(:stdout) { should contain 'node: 10.10.0' }
end
include_examples 'os release', 'Alpine Linux'
end
require 'spec_helper'
require 'shared_examples/release'
describe 'gerbv' do
before(:all) do
@image = Docker::Image.build_from_dir(image_path('gerbv'))
set :os, family: :debian
set :backend, :docker
set :docker_image, @image.id
set :docker_container_create_options, { 'Entrypoint' => ['/bin/sh'] }
end
describe package('gerbv') do
it { should be_installed }
end
include_examples 'os release', 'Ubuntu 18.04'
end
However when running bundle exec rspec
it is quite clear that the same container is being used to run each spec file. I have confirmed this by printing out the running containers before each of the examples. This is of course causing the specs to fail for one of the files (whichever runs second).
When the files are run independently using bundle exec rspec path/to/file
then all the specs pass.
Is there any way to force a container to be spun down after the examples in one file have run and a new container created for the other set of examples?
I found a way to solve the problem, albeit a pretty hacky one. The key to this problem lay in how the container is finally released. When there are no longer any references pointing to the Docker
instance it will be garbage collected and the container killed and deleted. However the object instance is held in a class level variable as a singleton in the base class. It would seem to me the only way to "reset" specinfra is to call the clear
method inherited on the Docker
class.
In the end the following solved the problem and the correct class is being used to run each spec.
after(:all) {
Specinfra.backend.class.clear
}
It would be great to know there is a better way to access this methods without having to rely on a method not exposed through the serverspec
gem.