1

When a new puppet module is created in Geppetto, manifests, spec and tests folders are created as well. The init.pp which resides in the manifests folder looks as follows:

define X (
    $version = "",
    $installer = "",
    $installer_extension = ""
) {
    file { "${name}_installer_copied_to_temp_directory":
        path => "c:/temp/${name}-${version}.${installer_extension}",
        source => "puppet:///files/${installer}.${installer_extension}",
        before => Exec["${name}_installed"],
        require => File["c:/temp"];
    }
}

The associated init.pp which resides in the tests folder looks as follows:

include X

If TDD in puppet makes sense, how to create a test for the define X snippet and how to run the tests in Geppetto?

030
  • 10,842
  • 12
  • 78
  • 123

2 Answers2

2

It does make sense!

I'd begin by looking at rspec-puppet. It provides you with custom RSpec matchers that will help you test your Puppet resources.

I'm not sure about what the boilerplate created by Geppetto includes, but running rspec-puppet-init at the root of your module will set you up for it.

In your case, you should probably begin by creating a specs/defines/X_spec.rb file and create a few test cases with variations on the define's inputs which test that the included File resource has the right attributes.

You can check rspec-puppet's tutorial for examples on how to write your test cases.

Be aware that you're not supposed to test if a file was created in the disk. This is Puppet's domain (not your module's), and is already tested in Puppet's codebase.

cassianoleal
  • 2,556
  • 19
  • 22
  • Thank you for the answer. 1) Could you indicate whether this works on Windows as well as the error `C:/puppet/sys/ruby/lib/ruby/1.8/fileutils.rb:338:in symlink': symlink() functiois unimplemented on this machine (NotImplementedError)` is thrown if `rspec-puppet-init` has been executed and 2) whether all the tests could be run by executing one command instead of executing `rspec-puppet-init` for each module individually. Eventually I would like to run nightly builds by Jenkins for example. – 030 Feb 04 '14 at 20:40
  • I will run some tests on the puppet master itself and let you know the outcome. – 030 Feb 04 '14 at 20:46
  • Executing `rspec-puppet-init` on the puppet master results in the following errors: `/var/lib/gems/1.8/gems/puppet-3.4.2/lib/puppet/indirector/data_binding/hiera.rb:4: uninitialized constant Puppet::DataBinding (NameError) from /usr/lib/ruby/vendor_ruby/1.8/rubygems/custom_require.rb:36:in `gem_original_require' from /usr/lib/ruby/vendor_ruby/1.8/rubygems/custom_require.rb:36:in `require'` – 030 Feb 04 '14 at 21:01
  • 1) It might not work in Windows since it relies on some symlinks on the filesystem (which are not supported by NTFS); 2) For unit tests, you'd write one test suite per module and run them from within the module's root path. This is how it should be, after all we're talking about testing units of code, not integration. That said, `rspec-puppet-init` is not what you use to *run* your tests. That command creates the necessary boilerplate for you to write unit tests using rspec. After writing the tests, you execute them by running `rspec`. – cassianoleal Feb 05 '14 at 00:33
  • Thank you for the advices. I have implemented rspec-puppet and created some tests. However, I am unable to test `custom types`. I have posted another question and I was wondering whether you know how to test custom types in puppet (http://stackoverflow.com/questions/22894798/how-to-test-custom-types-using-rspec-puppet). – 030 Apr 09 '14 at 19:57
0

Just to clarify at the higher level, the way that you do TDD in Puppet with rspec-puppet may be a little bit different from TDD you've done in other languages. Rspec-puppet only tests the generated catalog; it does not "smoke test" in the way that you might think of first, but it works very nicely for unit testing.

For example of what it is NOT for, say that in the general package-file-service paradigm, there's some environment-specific reason that the package might not install -- like, it conflicts with another RPM. Rspec-puppet can't test or catch things like this because it is only examining the catalog that gets generated; not the actual application of that catalog on a real system.

In general, a great approach for getting started with testing is to identify (a) branching logic and (b) varying data/values in your module. Write your tests against all logic branches, as a first step, and test both valid, invalid, and outlier values for variables that may be in your code.

In the above example, there really isn't much in the way of logic, but you might test what happens when odd values for $name or $version get put in; you want your puppet code to fail gracefully, because unhandled puppet errors are not, as a rule, the most communicative and clear of errors.

At the absolute minimum...

it { should compile }

(Getting it running cleanly after install can be a bit of a bear, it's true. I also use puppetlabs_spec_helper with it.)

neshura
  • 81
  • 1
  • 4