For a couple of weeks there is hiera integration in rspec-puppet.
Basic Spec setup
You will need a couple of files for puppet module rspec testing:
Gemfile
# Install via
# bundle install --path vendor/gems
#
source "https://rubygems.org"Rakefile
gem "mocha", :require => false
gem 'puppet', '>= 3.1.1'
gem 'puppet-lint'
gem 'facter', '>= 1.6.10'
gem 'rspec-puppet', :git => "https://github.com/rodjek/rspec-puppet.git"
gem 'rake', '>= 0.9.2'
gem 'puppetlabs_spec_helper', '0.3.0'
gem 'test-unit'
require 'rake'spec/spec_helper.rb
require 'rake/tasklib'
require 'rspec/core/rake_task'
require 'rubygems'
require 'puppetlabs_spec_helper/rake_tasks'
require 'puppet-lint'
desc "Run the tests"
RSpec::Core::RakeTask.new(:test) do |t|
t.rspec_opts = ['--color', '-f d']
t.pattern = 'spec/*/*_spec.rb'
end
desc 'Run puppet-lint on the one manifests'
task :onelint do
PuppetLint.configuration.with_filename = true
linter = PuppetLint.new
matched_files = FileList['spec/fixtures/modules/one/manifests/**/*.pp']
matched_files.to_a.each do |puppet_file|
linter.file = puppet_file
linter.run
end
fail if linter.errors? || (
linter.warnings? && PuppetLint.configuration.fail_on_warnings
)
end
task :default => [:spec_prep, :test, :onelint, :spec_clean]
require 'test/unit'
require 'mocha/setup'
require 'puppetlabs_spec_helper/module_spec_helper'
require 'puppet/indirector/hiera'
require 'hiera'
fixture_path = File.expand_path(File.join(__FILE__, '..', 'fixtures'))
# include common helpers
support_path = File.expand_path(File.join(File.dirname(__FILE__), '..',
'spec/support/*.rb'))
Dir[support_path].each {|f| require f}
RSpec.configure do |c|
c.config = '/doesnotexist'
c.manifest_dir = File.join(fixture_path, 'manifests')
c.mock_with :mocha
end
Fixtures
If your module require other modules (e.g. stdlib functions) you have to include them using fixtures repositories. Add your own module as a symlink:
.fixtures.yaml
fixtures:
repositories:
stdlib: "https://github.com/puppetlabs/puppetlabs-stdlib.git"
concat: "https://github.com/puppetlabs/puppetlabs-concat.git"
symlinks:This will create all required directory structures in spec/fixtures/modules.
<your module name>: "#{source_dir}"
Hiera Configuration
Add a hiera.yaml and a hiera data file to your spec/fixtures:spec/fixtures/hiera/hiera.yaml
---
:backends:
- yaml
:hierarchy:
- test
:yaml:
:datadir: 'spec/fixtures/hiera'
spec/fixtures/hiera/test.yaml
---
myvariable: 'myvalue'
Hiera Integration
Only minor changes are required to integrate hiera lookups into your spec tests.The following example is taken from my stdmodule on github (https://github.com/tuxmea/tuxmea-stdmodule.git)
spec/classes/<classname>_spec.rb
require 'spec_helper'
hiera_file = 'spec/fixtures/hiera/hiera.yaml' # <- required to find hiera configuration file
# test our main class (init.pp)
describe 'stdmodule', :type => :class do # <- set the class name
# test without hiera lookup (using class defaults)
context 'without hiera data' do
it { should contain_class('stdmodule') } # <- check for classes included
it { should contain_class('stdmodule').with_myparam('foo') } # <- check for classes with parameters
it { should contain_class('stdmodule::basic') } # <- check for subclasses
it { should contain_class('stdmodule::package_file_service') }
it { should contain_stdmodule__defines('foobar_define') } # <- check for defines
end
# test with explicit params given on class definition
context 'with explicit data' do
let(:params) {{ # <- set explizit params
:myparam => 'newvalue'
}}
it { should contain_class('stdmodule').with_myparam('newvalue') }
end
# test with explicit hiera lookup
context 'with explicit hiera lookup' do
# set hiera_config
let (:hiera_config) { hiera_file }
hiera = Hiera.new(:config => hiera_file) # <- use Hiera ruby class
variable = hiera.lookup('stdmodule::myparam', nil, nil) # <- do hiera lookup
let (:params) {{
:myparam => variable # <- set parameter to hiera lookup
}}
it { should contain_class('stdmodule').with_myparam(variable) }
end
end
With all respect given to your efforts, this is actually wrong...
ReplyDeleteCompare what you have done under the context "with explicit data" to what you have done under the context "with explicit hiera lookup." They are actually one and the same.
In both cases, you explicitly passed a parameter into the class under test. It does not matter that in the second case, the _test code_ got the value for that parameter from hiera. The method of providing the data _to_ the class under test is no different in the two contexts. This means you have tested the same thing twice.
What does _not_ get covered in this test is the scenario where no parameters are explicitly passed to the class under test and puppet take it upon itself to try and resolve values for each parameter from hiera. _That_ is missing from here.
All that being said, I am having a great deal of difficulty figuring out how to actually make the missing test scenario work as described. The documentation is spotty and I actually found this blog post of yours while trying to find the answer.