You are browsing a read-only backup copy of Wikitech. The live site can be found at wikitech.wikimedia.org

Puppet coding/testing

From Wikitech-static
< Puppet coding
Revision as of 16:26, 24 January 2017 by imported>Hashar
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Running

Some modules have test suites using the ruby test runner rspec and a set of rake tasks to run linting check (valid manifests, puppet-lint, hiera yaml files, erb templates). The ruby dependencies are listed in /Gemfile and are installed via bundler. To install all dependencies and later run a command in that environment:

bundle install

bundle exec <some command>

Assuming a module has a Rakefile and tests defined in a spec sub directory, one can run all tests via:

bundle exec rake syntax bundle exec rake puppet-lint bundle exec rake spec

You can list the various rake tasks via bundle exec rake -T or for a tree of the task dependencies bundle exec rake -P.

Rake explained

The /Gemfile ask for the rubygem puppetlabs_spec_helper ([www.rubydoc.info/gems/puppetlabs_spec_helper/ doc]) which contains several predefined rake tasks. Hence in a module one just have to create a Rakefile with:

require 'puppetlabs_spec_helper/rake_tasks'
$ cd modules/mymodule
$ bundle exec rake -T
rake beaker                # Run beaker acceptance tests
rake beaker_nodes          # List available beaker nodesets
rake build                 # Build puppet module package
rake check:dot_underscore  # Fails if any ._ files are present in directory
rake check:git_ignore      # Fails if directories contain the files specified in .gitignore
rake check:symlinks        # Fails if symlinks are present in directory
rake check:test_file       # Fails if .pp files present in tests folder
rake clean                 # Clean a built module package
rake compute_dev_version   # Print development version of module
rake coverage              # Generate code coverage information
rake help                  # Display the list of available rake tasks
rake lint                  # Run puppet-lint
rake release_checks        # Runs all nessesary checks on a module in preparation for a release
rake spec                  # Run spec tests in a clean fixtures directory
rake spec_clean            # Clean up the fixtures directory
rake spec_prep             # Create the fixtures directory
rake spec_standalone       # Run spec tests on an existing fixtures directory
rake syntax                # Syntax check Puppet manifests and templates
rake syntax:hiera          # Syntax check Hiera config files
rake syntax:manifests      # Syntax check Puppet manifests
rake syntax:templates      # Syntax check Puppet templates
rake validate              # Check syntax of Ruby files and call :syntax and :metadata_lint
$

The syntax* tasks come from the rubygem puppet-syntax.

The spec* tasks are helper to run rspec taking care of preparing test fixtures and tearing them down.

rspec-puppet

To tests puppet resources, we rely on rspec-puppet an helper on top of the ruby test runner rspec. rspec-puppet provides utilities to setup puppet, compile a catalog and has built-in assert methods to run against the catalog.

A minimal case requires a Rakefile, an helper file to be read by each test, and a spec. At first the Rakefile reuse the puppetlabs_spec_helper rake tasks described in the previous section:

Rakefile:

require 'puppetlabs_spec_helper/rake_tasks'

The tests are placed in sub directories of spec/ based on the type of Puppet resource being tested. That convention lets rspec-puppet properly setup the environment. rspec find tests by crawling the hierachy looking for files with the suffix _spec.rb. The hierarchy is:

spec/
  ├── applications/
  ├── classes/
  ├── defines/
  ├── functions/
  ├── hosts/
  ├── types/
  └── types_aliases/

We also need common code to initialize Puppet and point it to a fixture directory, that is where rspec-puppet will create a dummy manifests/site.pp and inject required modules.

Create spec/spec_helper.rb:

require 'rspec-puppet'

fixture_path = File.expand_path(File.join(__FILE__, '..', 'fixtures'))

RSpec.configure do |c|
  c.module_path = File.join(fixture_path, 'modules')
  c.manifest_dir = File.join(fixture_path, 'manifests')
end

The file will be required by each of the specs.


Given a puppet module mymodule consisting of a single class in manifests/init.pp:

class mymodule {
}

We first have to instruct rspec-puppet to inject our module in the fixture directory. To do so create a /.fixtures.yml:

fixtures:
    symlinks:
        mymodule: "#{source_dir}"

Since we will test a class, we create a mymodule_spec.rb file under spec/classes/:

require 'spec_helper'

# We will act on the resource "mymodule"
describe 'mymodule' do
  it { should.compile }
end

Finally some fancy configuration of rspec via /.rspec:

--format doc
--color

And we can run the spec:

$ bundle exec rake spec

mymodule
  should compile into a catalogue without dependency cycles

Finished in 0.07349 seconds (files took 0.4312 seconds to load)
1 example, 0 failures
$

Success!

Resources

https://github.com/rodjek/rspec-puppet