Author avatar

Sigu Magwa

Playing with RSpec from IRB

Sigu Magwa

  • Jan 10, 2019
  • 2 Min read
  • 2,796 Views
  • Jan 10, 2019
  • 2 Min read
  • 2,796 Views
Ruby
Ruby on Rails

Introduction

This is a quick guide showing you necessary steps you should take to make rspec work on irb.

Implementation

Lets start by loading rspec core and expectations.

1require 'rspec/core' # this is what really runs your tests
2require 'rspec/expectations' # readable syntax for checking properties of your code
ruby

We then include the matchers modules.

1include RSpec::Matchers # rspec will NOT automatically include this for you if you are using irb
ruby

With this we can now test out our expectations:

1>> expect(1).to eq(1)
2=> true
ruby

Whooohoo! You are good to go.. Not really, try this out.

12.3.0 :003 > array_hashes = [{lol: nil}]
2 => [{:lol=>nil}]
32.3.0 :005 > include RSpec::Matchers
4 => Object
52.3.0 :006 > expect(array_hashes).to include(have_key(:lol))

You will encounter an error as shown below:

1TypeError: wrong argument type RSpec::Matchers::BuiltIn::Has (expected Module)
2        from (irb):6:in `include'
3        from (irb):6
4        from /usr/local/rvm/rubies/ruby-2.3.0/bin/irb:11:in `<main>'

If you read closely into the error it expects a Module as an argument, this is because when using irb we are running in the main ruby object. This object has another method called include that has presidence over rspec's include method

To work around this, we can prepend RSpec::Matchers onto main's singleton class:

1$ irb
2irb(main):001:0> require 'rspec/expectations'
3=> true
4irb(main):002:0> singleton_class.prepend RSpec::Matchers
5=> #<Class:#<Object:0x007ff08a8d6620>>
6irb(main):003:0> array_hashes = [{lol: nil}]
7=> [{:lol=>nil}]
8irb(main):004:0> expect(array_hashes).to include(have_key(:lol))
9=> true

We encountered this problem while doing a mob session at AgileVentures and raised the issue on the rspec expectations github page where we got this hack.