1

Is there a standard pattern for writing spec tests for a puppet module, that correctly creates the custom facts that are required by the modules that the tested module includes?

I have a module whose class includes puppetlabs/mongodb, which uses the custom fact ::root_home (which is created by puppetlabs/stdlib).

Looking at the test code for mongodb, (in particular spec_helper_local.rb), I see code that creates the :root_home fact for testing.

But, in my own module, unless I do something to create that fact in my own test code, my test fails with "Evaluation Error: Unknown variable," which makes perfect since since nothing in the test suite is creating that fact.

Now I could just create the fact in the spec_helper_local.rb file for my module, but that just kicks the problem upstairs to whoever includes my module in theirs.

How should I deal with this? Has anyone already written code that recursively descends into included modules and creates the required facts for testing?

Chris Owens
  • 1,107
  • 1
  • 10
  • 15
  • 2
    The spec helper local idea is not bad, but also consider placing it within a `let` block inside the test spec itself. There is no optimal way of doing this as far as I know, which is what you want. – Matthew Schuchard Sep 20 '16 at 13:02

2 Answers2

0

Adding the custom fact to your test suite setup is exactly what you should be doing.

As you correctly assert, this will not help out the downstream users of your module, but that misses the point of a test suite: fully describing the environment in which a module is evaluated.

You can look into rspec-puppet-facts to setup default facts for all your tests (and gain some other nifty capabilities along the way).

David Schmitt
  • 58,259
  • 26
  • 121
  • 165
0

I agree, it is very annoying to have to add mocking to make realistic tests of your use of third party code. It is especially annoying since your tests can fail at any time due to changes in the internals of that code, e.g., a sudden introduction of the root_home fact from stdlib.

I have added at the top of my spec/spec_helper.rb:

if ENV.include? 'MODULEPATH'
  top_path = File.dirname(File.dirname(__FILE__))
  ENV['FACTERLIB'] = ENV['MODULEPATH'].split(/:/).map do |p|
    p.start_with?('/') ? p : File.join(top_path, p)
  end.map do |p|
    Dir.glob(File.join(p, '*/lib/facter'))
  end.flatten.join(':')
end

When the Facter library loads, it will honour the FACTERLIB environment variable and evaluate all the custom facts supplied by the modules in your environment.

A typical value for MODULEPATH is "design:modules" when testing environments, and "spec/fixtures/modules" when testing modules.