Coder Social home page Coder Social logo

rspec_intro's Introduction

Rspec testing Puppet modules

What ?

Rspec tests describe the wanted functionality (expectations) and allows automated testing of them. Complete tests describe all functional requirements for a module.

Why ?

Help to find errors, Logical errors, conceptual errors and also errors caused by the used software environment. Tests ease maintaining and implementation of new features into unknown or complex modules. The idea of continuous integration only works with automated tests.

Recommendations

Right From The Start

Create the tests simultaneously while writing the code. While developing, it is best known what is really essential and where the stumbling blocks are to be found. In an ideal world you would define the required behaviour (tests) first before you start to implement the code of the module.

Structure

Write the test on the motto: "from the general to the specific"

First you should test the default behaviour of the module. What does the module when called without using any optional parameter. You could also add a test which uses most to all features at once. This depends on the case of application.

After the basic functionallity is fully tested including all details, it is sufficient to only verify individual aspects in later tests. When testing different values for a parameter, it is fair enough to only check the affected conditions.

Example: puppet-module-autofs (https://github.com/gusson/puppet-module-autofs)

Testing the complete resource:

it do
  should contain_service('autofs').with({
    'ensure'    => 'running',
    'name'      => 'autofs',
    'enable'    => 'true',
    'require'   => 'Package[autofs]',
    'subscribe' => ['File[autofs_sysconfig]','File[auto.master]'],
  })
end

Testing an individual aspect only:

it { should contain_service('autofs').with_ensure('stopped') }

Crosschecking

Use cross checks where it makes sense. Cross checks could check that function or class calls are not included. Resource parameters that shouldn't be set and error messages because of failures should be tested.

Testing absence:

it { should_not contain_file('awk_symlink') }
it { should_not contain_exec('locale-gen') }
it { should have_pam__service_resource_count(0) }
it { should contain_file('/etc/logrotate.d/apache').without_owner('root') }
it { should contain_file('postfix_main.cf').without_content(/^virtual_alias_maps = hash:\/etc\/postfix\/virtual$/) }

Testing error messages:

it 'should fail' do
  expect do
    should contain_class(subject)
  end.to raise_error(Puppet::Error, /Pam: vas is not supported on #{v[:osfamily]} #{v[:release]}/)
end

Submodules

Each class and define should be tested isolated on it's own. When a class (init.pp) calls another (submodule.pp) you only need to test the call and the used parameters itself. Don't test the outcome of the other class. Confide!

Example:

manifest/init.pp

create_resources('pam::service',$services)

manifest/service.pp

file { "pam.d-service-${name}":
  ensure  => $file_ensure,
  path    => "${pam_config_dir}/${name}",
  content => $my_content,
  owner   => 'root',
  group   => 'root',
  mode    => '0644',
}

Good testing: spec/classes/init_spec.rb

let (:params) { {:services => { 'testservice' => { 'content' => 'foo' } } } }

it { should have_pam__service_resource_count(1) }

it do
  should contain_pam__service('testservice').with({
    'content' => 'foo',
  })
end

Bad testing: spec/classes/init_spec.rb

let (:params) { {:services => { 'testservice' => { 'content' => 'foo' } } } }

it {
  should contain_file('pam.d-service-testservice').with({
    'ensure'  => 'file',
    'path'    => '/etc/pam.d/testservice',
    'owner'   => 'root',
    'group'   => 'root',
    'mode'    => '0644',
  })
}

it { should contain_file('pam.d-service-testservice').with_content('foo') }

Boundaries

Rspec testing can't deliver the proof of being free from errors. It can only proof that the particular test cases have been met. It can only find errors in case a test does exist. Therefore each functional change should (mandatory) be delivered with corrosponing tests.

Weblinks

First-hand Information:

Rspec tipps (not Puppet related):

Verbose output while testing

~/.bashrc:

export SPEC_OPTS="--format documentation"

rspec_intro's People

Stargazers

Jonathan Bower avatar Anders Larsson avatar

Watchers

James Cloos avatar Phil Friderici avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.