First "should be_installed" in test always fails on Windows

1.3k views Asked by At

First off, I'm using serverspec 2.3.1 and specinfra 2.4.2, with Ruby 1.9.3p550

I am still investigating the problem, but I figured I'd give a shot at asking here in case someone encountered the problem before (and if not and I figure it out, maybe the next person who does encounter it will find this answer on Google).

The goal is to have a spec file with all the softwares that should be installed on the test system. What is weird though is that no matter what I write, the first time I do it { should be_installed }, it will fail. No exception.

The code below shows what I mean:

require 'acceptance_helper'

describe package('7-Zip 9.22 (x64 edition)') do
  it { should be_installed }
end

describe package('7-Zip 9.22 (x64 edition)') do
  it { should be_installed }
end

describe package('Zend Server') do
  it { should be_installed }
end

describe package('SQL Server 2012 Management Studio') do
  it { should be_installed }
end

describe package('Microsoft SQL Server 2012 (64-bit)') do
  it { should be_installed }
end

When I run this file, I'll get the first test that says 7-Zip is not installed and the second test will say it is. Anything I put as the first test does the same thing.

Package "7-Zip 9.22 (x64 edition)"
  should be installed (FAILED - 1)

Package "7-Zip 9.22 (x64 edition)"
  should be installed

Package "Zend Server"
  should be installed

Package "SQL Server 2012 Management Studio"
  should be installed

Package "Microsoft SQL Server 2012 (64-bit)"
  should be installed

Failures:

  1) Package "7-Zip 9.22 (x64 edition)" should be installed
     Failure/Error: it { should be_installed }
     TypeError:
       can't convert Symbol into Integer
       uname -s
       #< CLIXML
<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04"><S S="Error">The term 'uname' is not recognized as the name of a cmdlet, function, script fi_x000D__x000A_</S><S S="Error">le, or operable program. Check the spelling of the name, or if a path was inclu_x000D__x000A_</S><S S="Error">ded, verify that the path is correct and try again._x000D__x000A_</S><S S="Error">At line:1 char:6_x000D__x000A_</S><S S="Error">+ uname &lt;&lt;&lt;&lt;  -s_x000D__x000A_</S><S S="Error">    + CategoryInfo          : ObjectNotFound: (uname:String) [], CommandNotFou _x000D__x000A_</S><S S="Error">   ndException_x000D__x000A_</S><S S="Error">    + FullyQualifiedErrorId : CommandNotFoundException_x000D__x000A_</S><S S="Error"> _x000D__x000A_</S></Objs>
 # ./spec/acceptance/192.168.0.70/all_required_applications_are_installed_spec.rb:4:in `block (2 levels) in <top (required)>'

Finished in 25.96 seconds (files took 0.99763 seconds to load)
5 examples, 1 failure

Failed examples:

rspec ./spec/acceptance/192.168.0.70/all_required_applications_are_installed_spec.rb:4 # Package "7-Zip 9.22 (x64 edition)" should be installed

What's unreal to me is that only the first test will fail, so I'm really not sure what could be happening. I'll investigate and update this post as I go, but if anyone has ever encountered this, I'd really like to hear how/if you fixed this!

Edit: With the error message and the way ServerSpecs tests for packages on Windows, I thought the command was badly executed, but it turns out the error happens even before the command is run. At least it looks like it, since in Intellij IDEA, when I put a break point on line 7 of specinfra/command/windows/base/package.rb (exec "(FindInstalledApplication -appName '#{package}' #{version_selection}) -eq $true"), the break point is never reached, the test fails and it goes to the next test.

Edit 2: Managed to isolate the problem a bit more, it seems to happen in specinfra\helper\os.rb. I'm new to Ruby, so it's a bit hard to debug, but I'm guessing something isn't initialized properly on the first run of whatever ServerSpec/SpecInfra uses to detect OS.

1

There are 1 answers

2
gCardinal On BEST ANSWER

Well, it turns out I'm silly and can't read documentation properly. They say on Serverspec's documentation that Windows OS need to be specified in the spec_helper and I had only copy/pasted the example helper from their Windows doc.

This is my helper file now, notice the set :os line

require 'serverspec'
require 'winrm'
require 'yaml'

set :backend, :winrm
set :os, :family => 'windows', :release => '2008', :arch => 'x64'

base_path = File.dirname(File.expand_path(__FILE__))
config = YAML.load_file(File.join(base_path, 'config.yml'))

user = 'vagrant'
pass = 'vagrant'
endpoint = "http://#{config['host_ip']}:5985/wsman"

winrm = ::WinRM::WinRMWebService.new(endpoint, :ssl, :user => user, :pass => pass, :basic_auth_only => true)
winrm.set_timeout 300 # 5 minutes max timeout for any operation
Specinfra.configuration.winrm = winrm