Puppet Tech Debt Day 3, excluding OS testing

When using rspec-puppet-facts, there’s one minor limitation: it tests all the supported operating systems, even if a class is designed for a specific OS or family. You can easily skip the rspec-puppet-facts in a specific test, though it kind of defeats the purpose for your general purpose operating systems (if your OS type isn’t in facterdb – currently a certainty with network devices – you have to go around it anyway). But what if you want to keep using the facts and just exclude one or two compatible OSes? We were bandying this about on the Puppet slack yesterday and came up with a solution. Thanks to Daniel Schaaff for determining the syntax for this pattern!

Here’s what the per-OS portion of a spec test file looks like once you add rspec-puppet-fact:

on_supported_os.each do |os, facts|
  context "on #{os}" do
    let(:facts) do
      facts
    end

    it { is_expected.to contain_class('profile::unattendedupgrades')}
    it { is_expected.to contain_class('profile::linux::apt_source_list')}
  end
end

Obviously you don’t expect, or want, apt-related resources to apply to non-Debian OSes. We can filter that out using the osfamily fact. This lets us keep the on_supported_os.each pattern in our spec tests but preserve the functionality we want. Here’s what that looks like:

on_supported_os.each do |os, facts|
  context "on #{os}" do
    let(:facts) do
      facts
    end

    if facts[:osfamily] == 'Debian' then
      it { is_expected.to contain_class('profile::unattendedupgrades')}
      it { is_expected.to contain_class('profile::linux::apt_source_list')}
    end
  end
end

You can apply this wherever you want in your tests. If the class profile::unattendedupgrades were to apply to all OSes, move it out of the if block. You can also limit by kernel or whether or not selinux is enabled – or by a custom fact you generated.

Update: I came up with this pattern for my linux-only classes, to future proof against adding Windows as a supported OS:

describe 'profile::access_request', :type => :class do
  on_supported_os.each do |os, facts|
    next unless facts[:kernel] == 'Linux'

Leave a comment