Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

defined types facts as default parameter not working #13

Closed
b4ldr opened this issue Sep 20, 2021 · 3 comments
Closed

defined types facts as default parameter not working #13

b4ldr opened this issue Sep 20, 2021 · 3 comments

Comments

@b4ldr
Copy link

b4ldr commented Sep 20, 2021

Describe the Bug

With a defined that has a default parameter which uses a fact for the default value e.g.

define example::rspec_define (
  $fact_parameter = $facts['os']['distro']['codename']
) {
  file{'/tmp/T291374':
    ensure  => file,
    content => $fact_parameter
  }
}

Testing using rspec-puppet-tests has no affect on the default value. It appears that all tests use the last value in the on_supported_os iterator.

The test i used is:

describe 'example::rspec_define' do
  on_supported_os(test_on).each do |os, facts|
    let(:facts) { facts }
    let(:title) { "test-#{os}" }
    context os do
      context 'test' do
        it { is_expected.to compile }
        it { is_expected.to contain_file('/tmp/T291374').with_content(/#{facts[:os]['distro']['codename']}/) }
      end
    end
  end
end

Expected Behaviour

All test should pass

Actual Behaviour

The file content test above fails when testing debian-10-x86_64 with the following error

  1) example::rspec_define debian-10-x86_64 test is expected to contain File[/tmp/T291374] with content =~ /buster/
     Failure/Error: it { is_expected.to contain_file('/tmp/T291374').with_content(/#{facts[:os]['distro']['codename']}/) }
       expected that the catalogue would contain File[/tmp/T291374] with content set to /buster/ but it is set to "stretch"
     # ./spec/defines/rspec_define_spec.rb:10:in `block (5 levels) in <top (required)>'

Steps to Reproduce

I have created a specific repo to demonstrate this issue
Steps to reproduce the behavior:

  1. git clone https://github.com/b4ldr/T291374/
  2. cd T291374
  3. bundle install
  4. bundle exec rake spec
@michaeltlombardi
Copy link

@b4ldr taking a look through, it seems like the issue might be with the facts caching in on_supported_os which is actually defined/maintained in voxpupuli/rspec-puppet-facts as you can see here:

https://github.com/voxpupuli/rspec-puppet-facts/blob/master/lib/rspec-puppet-facts.rb#L31-L50

I suspect this issue should be moved to that repository where the maintainers will have better context and availability to solve the problem at the right level.

@ekohl
Copy link

ekohl commented Sep 28, 2021

@b4ldr I would recommend to use different names so you don't shadow, but that's not the real issue. You don't scope the facts properly. What you must do is to call let inside context:

describe 'example::rspec_define' do
  on_supported_os(test_on).each do |os, os_facts|
    context os do
      let(:facts) { os_facts }
      let(:title) { "test-#{os}" }
      context 'test' do
        it { is_expected.to compile }
        it { is_expected.to contain_file('/tmp/T291374').with_content(/#{facts[:os]['distro']['codename']}/) }
      end
    end
  end
end

This has to do with rspec itself where it first generates classes but it keeps a reference to the facts variable on the describe level. That level is shared between all tests and you overwrite it in every iteration of the loop. After the collection phase it executes the tests which point to the same facts hash. By using the let block there is proper scoping.

You can see this as well with this test:

require 'voxpupuli/test/spec_helper'
test_on = { supported_os: [ 'operatingsystem' => 'Debian', 'operatingsystemrelease' => ['9','10']]}
describe 'example::rspec_define' do
  on_supported_os(test_on).each do |os, os_facts|
    let(:facts) { os_facts }
    let(:title) { "test-#{os}" }
    context os do
      it { is_expected.to compile }
      it { is_expected.to contain_file('/tmp/T291374').with_content(/#{facts[:os]['distro']['codename']}/) }
    end
  end
end

This results in:

example::rspec_define
  debian-10-x86_64
    is expected to compile into a catalogue without dependency cycles
    is expected to contain File[/tmp/T291374] with content =~ /stretch/
  debian-9-x86_64
    is expected to compile into a catalogue without dependency cycles
    is expected to contain File[/tmp/T291374] with content =~ /stretch/

Note how the context is printed correctly but then the facts have an old value.

Edit: I just realized that with voxpupuli/rspec-puppet-facts#132 this wouldn't be a problem: all this complex boiler plate is hidden.

@b4ldr
Copy link
Author

b4ldr commented Sep 28, 2021

@ekohl thanks for the fix and explanation closing as #invalid

@b4ldr b4ldr closed this as completed Sep 28, 2021
wmfgerrit pushed a commit to wikimedia/operations-puppet that referenced this issue Sep 28, 2021
update spec test to test multiple distros:
 puppetlabs/rspec-puppet#13

Change-Id: I0fd23fdc44b57cb23d56233fb08c24a406aa4af6
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants