Search code examples
expectationsserverspec

Does Serverspec support expectations or do I have to use should?


I hear I should be using expectations rather than "should" statements in Serverspec

I have been Googling around for expectations that can be used for file matching but all of the tutorials I see for Serverspec use should rather than expect. Is this because Serverspec hasn't been updated to use expectations?

describe file('/etc/yum.conf') do
  it { should be_file }
  it { should be_owned_by 'root' }
  it { should be_grouped_into 'root' }
  it { should be_mode 644 }

  its(:content) { should match /^gpgcheck=1$/ }
  its(:content) { should match /^clean_requirements_on_remove=1$/ }
end

So how would I write the test using expectations instead of should?


Solution

  • Your first question:

    ... all of the tutorials I see for Serverspec use should rather than expect. Is this because Serverspec hasn't been updated to use expectations?

    No, it is mostly because the author of the Serverspec project has a preference for the "should" syntax, and that's why the Serverspec documentation continues to use it. He has explained here that:

    I'm using should syntax instead of expect syntax because I think should syntax is more readable than expect syntax and I like it.

    Using expect syntax is recommended way because adding should to every object causes failures when used with BasicObject-subclassed proxy objects.

    But the one-liner syntax used with the examples in this page doesn't add should to any objects, so this syntax doesn't cause the above problems. That's why I'm using the one-liner should syntax.

    Be aware that should and expect come from the rspec-expectations project, and the Serverspec author is correct "should" rather than "expect" is fine the way he is using it.

    There is more info on the original motivation for the expect syntax from the Rspec author Myron Marston here.

    Your second question:

    ... how would I write the test using expectations instead of should?

    If you still want to use the expect syntax, just replace should everywhere with is_expected.to everywhere. This works fine:

    describe file("/etc/passwd") do
      it { is_expected.to be_file }
      its(:content) { is_expected.to match /root/ }
    end
    

    You can also write it this way:

    describe "passwd file" do
      it "the passwd file should be a file" do
        expect(file("/etc/passwd")).to be_file }
      end
      it "and it should contain root" do
        expect(file("/etc/passwd").content).to match /root/
      end
    end
    

    Or even:

    describe file("/etc/passwd") do
      it { expect(subject).to be_file }
      it { expect(subject.content).to match /root/ }
    end
    

    See also: