0

I am trying to write the chefspec/unit test for my recipe. I am facing problem. I need to write the unit test case for below code. If I comment the last statement of my code, the test execute successfully but I have to catch that statement too as its the proper way to write. Thanks for helping.

powershell_script 'Delete ISO from temp directory' do
    code <<-EOH
            [System.IO.File]::Delete("#{iso_path}")
            [System.IO.File]::Delete("#{config_path}")
            EOH
    guard_interpreter :powershell_script
    only_if { File.exists?(iso_path)}
end
msanford
  • 11,803
  • 11
  • 66
  • 93
  • 1
    As I understand, you are trying to delete some files. Chef has `file` resource for that, you do not need powershell. – Draco Ater Feb 15 '17 at 07:20
  • @DracoAter I want to delete the ISO from the temporary directory only if it exists. I have used powershell resource for unit testing of this block and it works fine but I have to catch the condition too in order to write unit test properly – Aakash Oza Feb 15 '17 at 19:43
  • That's exactly what `file` resource does. It deletes the file, if the file exists. You should always prefer existing idempotent resources (like file, directory, template) to non-idempotent (like execute, bash, powershell_script). – Draco Ater Feb 16 '17 at 07:04

2 Answers2

0

So to start with, your code doesn't make sense. You have a guard_interpreter set but your guard clause is a Ruby code block, not a command string. Other than that, just test it like anything else. If you mean specifically how to test both the file existing and not existing, you would use rspec-mocks to set up File.exists? to return a canned value.

coderanger
  • 52,400
  • 4
  • 52
  • 75
0

First of all. If all you need is to delete a file, and according to the code that is the case, you should use file resource.

[iso_path, config_path].each do |path|
  file path do
    action :delete
  end
end

File is idempotent resource. Which means Chef checks for you, if the resource should be changed. In this case Chef will delete the file, only if that exists.

Powershell_script (and all the other script resources) are non-idempotent. Which means, you have check yourself, if the resource should be executed, by providing a guard. Guard is only_if or not_if block. You should remove guard_interpreter :powershell_script line, because you are actually writing ruby in the guard.

powershell_script 'Delete ISO from temp directory' do
  code <<-EOH
    [System.IO.File]::Delete("#{iso_path}")
    [System.IO.File]::Delete("#{config_path}")
    EOH
  only_if { File.exists?(iso_path) }
end

Now to testing. Testing file resource is easy, as I understand you already can do that. But testing powershell_script is harder: you must stub the File.exists?(iso_path) call. You can do it like that:

describe 'cookbook::recipe' do
  context 'with iso file' do
    let! :subject do
      expect( ::File ).to receive( :exists? ).with( '<iso_path_variable_value>' ).and_return true
      allow( ::File ).to receive( :exists? ).and_call_original
      ChefSpec::Runner.new( platform: 'windows', version: '2008R2' ).converge described_recipe
    end

    it { shold run_powershell_script 'Delete ISO from temp directory' }
  end

  context 'without iso file' do
    let! :subject do
      expect( ::File ).to receive( :exists? ).with( '<iso_path_variable_value>' ).and_return false
      allow( ::File ).to receive( :exists? ).and_call_original
      ChefSpec::Runner.new( platform: 'windows', version: '2008R2' ).converge described_recipe
    end

    it { shold_not run_powershell_script 'Delete ISO from temp directory' }
  end
end

Do you see how much more work you have to do comparing to testing file resource?

Draco Ater
  • 20,820
  • 8
  • 62
  • 86