Update: Well, this is embarassing. After I posted this, I received a comment within a few hours from @myronmarston. I’d originally written this matcher for RSpec2, and then had to convert my project to use RSpec3. I just blindly converted this matcher over. Myron pointed out that with RSpec3’s composable matchers, the functionality of this gem is built-in. It can be done as simply as:

its(:headers) { should include('server' => /nginx\/1\./) }

As such, I’ve yanked them gem and am leaving the code and blog post here just for posterity. This should probably not be used.

I’ve been working on a project to move my Linode VM to an Amazon EC2 instance; the entire instance is a “baked” AMI built by Puppet. Since I’d like to be able to rebuild this quickly, I’m using ServerSpec (which I have some non-technical issues with, but that’s a long story) to run full integration tests of the whole system - check that packages are installed, services are running, and even make live HTTP requests agsinst it.

One part of this was making live HTTP requests (from inside ServerSpec / rspec) and checking HTTP response headers. Unfortunately, RSpec doesn’t have a nice, clean way to make assertions about a hash item.

So, I wrote a little Ruby Gem to do this, rspec-matcher-hash-item. At the moment it just has one matcher, have_hash_item_matching. This operates on a hash, and takes two arguments, a key and a regex for the value. It allows me to do simple but useful things like:

  describe http_get(80, 'testapp1.jasonantman.com', '/testapp1234') do
    its(:headers) { should have_hash_item_matching('server', /nginx\/1\./) }

(The http_get serverspec matcher is coming in a future gem and blog post)

Among other things, it prints diffs on failure:

  2) privatepuppet::ec2::vhosts::testapp1 Http_get "" headers should include key 'server' matching /badvalue/
     On host `'
     Failure/Error: its(:headers) { should have_hash_item_matching('server', /badvalue/) }
       expected that hash[server] would match /badvalue/
       @@ -1,2 +1,6 @@
       -["server", /badvalue/]
       +"connection" => "close",
       +"content-type" => "text/plain",
       +"date" => "Sat, 21 Feb 2015 16:07:42 GMT",
       +"server" => "nginx/1.6.2",
       +"transfer-encoding" => "chunked",

Using the gem is as simple as including it in your Gemfile:

gem "rspec-matcher-hash-item"

And adding a line to your spec_helper.rb:

require 'rspec_matcher_hash_item'

Note that the gem is written for RSpec3.

This is available at rubygems.org or from GitHub. See GitHub for the documentation.


comments powered by Disqus