Search code examples
rspecpuppetrspec-puppet

How to define helper methods for manipulating the Puppet catalogue object


I have a bunch of repeated code that manipulates the Puppet catalogue object (notice the repeated content = lines):

require 'nokogiri'

describe 'role::jenkins' do
  before(:each) do
    @jobs = catalogue.resource_keys.select{|k,v| k == 'Jenkins::Jobs'}.map{|k,v| v}
  end

  it 'Jenkins jobs should be valid XML' do
    @jobs.each do |j|
      content = catalogue.resource('file', "/tmp/#{j}.xml").send(:parameters)[:content]
      result = Nokogiri::XML(content).errors.empty?
      if ! result
        puts "    Job #{j} does NOT have valid XML"
      end
      expect(result).to be true
    end
  end 

  it "XML should contain a variables.json snippet that is valid JSON" do
    @jobs.each do |j|
      content = catalogue.resource('file', "/tmp/#{j}.xml").send(:parameters)[:content]
      if content.match(/cat << EOF > #{json_file}.*?EOF/m)
        json_snippet = content.match(/#{json_file}(.*?)EOF/m)[1]
        expect { JSON.parse(json_snippet) }.to_not raise_error
      end
    end
  end
end

As can be seen, I have moved a long query into a before(:each) block and saved it in an instance variable. That makes it available in the it blocks.

What I do not understand is how I could define a method for the content = lines, like:

def content(file_name)
  catalogue.resource('file', file_name).send(:parameters)[:content]
end

If I knew how to do that I could clean up this code considerably. What I cannot figure out is where I could place this def block, if it is even possible to do this.


Solution

  • I have made a silly mistake (thought I had already tried something when actually I had not).

    The answer is just put the def inside the before block as well:

    require 'nokogiri'
    
    describe 'role::jenkins' do
      before(:each) do
        @jobs = catalogue.resource_keys.select{|k,v| k == 'Jenkins::Jobs'}.map{|k,v| v}
    
        def content(file_name)
          catalogue.resource('file', file_name).send(:parameters)[:content]
        end
      end
    
      it 'Jenkins jobs should be valid XML' do
        @jobs.each do |j|
          result = Nokogiri::XML(content("/tmp/#{j}.xml").errors.empty?
          if ! result
            puts "    Job #{j} does NOT have valid XML"
          end
          expect(result).to be true
        end
      end 
    
      it 'XML should contain a variables.json snippet that is valid JSON' do
        @jobs.each do |j|
          content = content("/tmp/#{j}.xml")
          if content.match(/cat << EOF > #{json_file}.*?EOF/m)
            json_snippet = content.match(/#{json_file}(.*?)EOF/m)[1]
            expect { JSON.parse(json_snippet) }.to_not raise_error
          end
        end
      end
    end
    

    Please let me know though if anyone can see any further improvements that could be made!