简体   繁体   中英

Rspec puppet module testing: access to included classes' custom facts

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?

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).

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, eg, 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM