Fixing and improving rspec tests

Today I stumbled across our puppet module for gluster. My goal for the next days:

  • modulesync with voxpupuli default settings
  • Fix rspec tests to work with our new test matrix (newer puppet versions and STRICT_VARIABLES=yes)
  • Make a new release for the forge
  • Add Arch Linux support
  • Make another release

Fixing rubocop the nice way:
The module has beed modulesynced before so there weren’t many changes, except for the conversion to the new Hash notation that got introduced in Ruby 1.9. These changes happend here and here. I recommend the following command to get a list of all failed cops:

bundle exec rubocop -c .rubocop.yml -D

Now we know the name of the cops and the files that need improvements. This allows us to try the awesome autofix function, but only for a certain cop or even a certain file (remember how to commit things, always small and logical changes):

bundle exec rubocop --only Style/HashSyntax --auto-correct my/awesome/file.rb

Bringing rspec to the next level of awesomeness:
Now we get to the failed rspec tests, here is one example:

  describe 'installing on Red Hat Enterprise Linux' do
    let :facts do
      {
        :osfamily => 'RedHat',
        :operatingsystem => 'RedHat',
        :operatingsystemmajrelease => '6',
        :architecture => 'x86_64',
      }
    end
    context 'when repo is true' do
      let :params do
        { :repo => true }
      end
      it 'should create gluster::repo' do
        should create_class('gluster::repo').with(
          :version => 'LATEST',
        )
      end
    end

The issue here is that the puppet module references a fact that isn’t used (so the cataloq compilation works) but also not present in our mocking (line 4-7). The old school solution is to add all accessed facts to all tests. This is a bit of copy and paste shit, but works. The module claims to support RHEL6 and 7, but the upper test only checks for RHEL6. I need to copy and paste the whole block to to also test on RHEL7, just with little data modification. This gets even mor anoying when you also support Debian based systemd and/or have a huge amount of tests.

The solution is rspec-puppet-facts. This can automatically mock every operating system specific fact, the list of needed operating systems comes from the metadata.json. The implementation:

  on_supported_os.each do |os, facts|
    context "on #{os}" do
      let(:facts) do
        facts
      end
      context 'with defaults' do
        it { should compile.with_all_deps }
        it 'should create gluster::repo' do
          should create_class('gluster::repo').with(
            version: 'LATEST',
          )
        end
....
      end
    end
  end

Here is the full implementation. rspec-puppet-facts allows us to simply iterate on the list of operating systems, and add all facts to rspec. Take a look at the nesting of contexts. The actual tests have to be nested in the context that adds the facts, because of the scoping.

Conclusion:
Playing a bit with rubocop and rspec-puppet-facts is a nice solution to heavily increase the code quality of existing tests, besides that you can also increase the amount of tests by looping at every OS.

This entry was posted in 30in30, General, Linux, Puppet. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

Time limit is exhausted. Please reload CAPTCHA.