【问题标题】:Assert that the Chef run included a recipe from another cookbook断言 Chef 运行包含来自另一本食谱的食谱
【发布时间】:2016-07-08 14:36:45
【问题描述】:
$ cat Gemfile | grep "'chefspec'\|'chef'"
  gem 'chef', '12.8.1'
  gem 'chefspec', '4.6.1'

$ cat cookbooks/foo/recipes/default.rb | grep include
include_recipe 'bar'

$ cat cookbooks/foo/metafata.rb | grep depends
depends 'bar'

bar 食谱中的所有资源运行chefspec 输出Untouched Resources:。 我遵循include recipe 断言,但它使用allow_any_instance_of,这可能不是最佳实践。 我使用它如下:

$ cat cookbook/foo/spec/recipes/default_spec.rb
describe 'foo::default' do
  cached(:chef_run) { ChefSpec::ServerRunner.converge(described_recipe) }
  let(:recipe) { instance_double(Chef::Recipe, cookbook_name: 'foo', recipe_name: 'default') }

  before do
    allow_any_instance_of(Chef::Recipe).to receive(:include_recipe).and_call_original
    allow_any_instance_of(recipe).to receive(:include_recipe).with('bar')
  end

  it 'includes recipes' do
    expect_any_instance_of(recipe).to receive(:include_recipe).with('bar')
  end
end

但是当我运行rspec 时,我得到以下错误:

foo::default
  includes recipes (FAILED - 1)

Failures:

  1) foo::default includes recipes
     Failure/Error: allow_any_instance_of(recipe).to receive(:include_recipe).with('bar')
       #<InstanceDouble(Chef::Recipe) (anonymous)> received unexpected message :ancestors with (no args)
     # ./vendor/cookbooks/foo/spec/recipes/default_spec.rb:32:in `block (2 levels) in <top (required)>'

Finished in 2.22 seconds (files took 1.72 seconds to load)
1 example, 1 failure

Failed examples:

rspec ./vendor/cookbooks/foo/spec/recipes/default_spec.rb:43 # foo::default includes recipes

能否解释一下这个问题:

  1. chefspec 可以运行所有包含的食谱的规范吗?如果是这样,我该如何配置?
  2. 如果前一个不可行,我该如何解决上述问题并消除包含的食谱的收敛(将其他食谱视为黑盒)?

更新:

还尝试了解决方案Stub (...) received unexpected message (...) with (no args),但没有帮助,并返回了不同的错误:

foo::default
  includes recipes (FAILED - 1)

Failures:

  1) foo::default includes recipes
     Failure/Error: allow(recipe).to receive(:ancestors).and_return(true)
       the Chef::Recipe class does not implement the instance method: ancestors. Perhaps you meant to use `class_double` instead?
     # ./vendor/cookbooks/foo/spec/recipes/default_spec.rb:31:in `block (2 levels) in <top (required)>'
     # ./vendor/cookbooks/foo/spec/recipes/default_spec.rb:37:in `block (2 levels) in <top (required)>'

Finished in 1.33 seconds (files took 1.4 seconds to load)
1 example, 1 failure

Failed examples:

rspec ./vendor/cookbooks/foo/spec/recipes/default_spec.rb:48 # foo::default includes recipes

【问题讨论】:

  • 如果我理解正确,您真正希望从覆盖报告中排除“酒吧”食谱资源,为此,它记录在自述文件的覆盖部分here 中使用add_filter coverage.start! 块。 Chefspec 不加载包含的食谱的测试,我不知道如何做到这一点,包括帮助程序/存根可能是一个想法,但 IMO 猜测太多了。
  • @Tensibai:首先谢谢您的回复。请注意,添加过滤器并不意味着说明书将不在运行列表中,它只是不会出现在覆盖率报告中,这意味着为包含的说明书创建了存根\模拟(在我们的例子中为bar)将必须复制到包含其他食谱的食谱中(在我们的例子中为foo),并且我们的代码重复很糟糕。其中更多,如果我的所有私人食谱都有一个spec_helper,则需要根据食谱修改全局或中心位置的过滤器。你有什么别的想法吗?
  • ChefSpec 是“以食谱为中心的”,您不应该为许多食谱使用通用的 spec_helper。假设您知道自己在做什么,则可以依次要求其他食谱规范。阻止包装的说明书资源运行通常是错误的模式,因为您也可能错过覆盖资源。所以tl;博士;您必须进行代码重复,这还不错,因为它会告诉您包装食谱的更新是否会破坏您的;)
  • @Tensibai:我已经利用了您在之前评论中提供的内容 - 在中心 spec_helper,我扩展了我的自定义过滤器 (ChefSpec::Coverage::Filter),拥有一个类(静态)变量,它包含排除列表,并且该变量可从外部访问(从特定规范内)。我想你把我带到了这里......我想给你一个关于潜在客户的信用,所以请将你的评论转换为答案,以便我可以将其标记为已解决。
  • 你应该写下你自己的答案和解决你的问题的细节,我只是在这里给出了提示;)

标签: chef-infra cookbook


【解决方案1】:

摘自天丝白评论:

如果我对您的理解正确,您真正希望的是从覆盖率报告中排除“酒吧”食谱资源,为此,它已记录在自述文件的覆盖率部分中,使用 coverage.start 中的 add_filter!堵塞。 Chefspec 不会加载包含的食谱的测试,我不知道如何做到这一点,包括帮助程序/存根可能是一个想法,但 IMO 猜测太多了。

【讨论】:

    猜你喜欢
    • 2013-06-24
    • 2015-09-17
    • 2014-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-25
    • 1970-01-01
    相关资源
    最近更新 更多