serverspec 使用了错误的容器

serverspec using wrong container

我有 2 个规范文件使用不同的 docker 图像,因此应该启动单独和不同的 docker 容器来 运行 示例。

在下面的代码片段中,我使用 serverspec gem 来测试我的容器

spec/dockerfile/ember_spec.rb

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

spec/dockerfile/gerbv_spec.rb

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

然而,当 运行ning bundle exec rspec 时,很明显 运行 每个规范文件都使用同一个容器。我已经通过在每个示例之前打印出 运行ning 容器来确认这一点。这当然会导致其中一个文件的规范失败(以 运行 秒为准)。

当文件 运行 独立使用 bundle exec rspec path/to/file 时,所有规格都通过。

在一个文件中的示例具有 运行 并为另一组示例创建新容器后,是否有任何方法可以强制停止容器?

我找到了解决问题的方法,尽管是一个很老套的方法。这个问题的关键在于容器最终如何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。在我看来,"reset" specinfra 的唯一方法是调用在 Docker class.

上继承的 clear 方法

最后,以下解决了问题,正确的 class 被用于 运行 每个规格。

after(:all) {
  Specinfra.backend.class.clear
}

很高兴知道有更好的方法来访问此方法,而不必依赖未通过 serverspec gem.

公开的方法