- Published on
Introduction to RSpec and Testing in Ruby
- Authors
- Name
- Curtis Warcup
 
 
RSpec is a testing framework for Ruby. It is the most popular testing framework for Ruby, and is used in conjunction with the Ruby on Rails framework. Let's take a look at how to get started with RSpec.
Basics of RSpec
Install the RSpec gem:
gem install rspec
- It's convention to put all your tests in a specfolder.
Writing Tests
Describe Blocks
- use describeto describe a method or class- describetells Rspec what code you're testing
- you'll see these messages when you run your tests
- the actual test code goes inside the describeblock between thedoandend
 
# inside spec/example_spec.rb
describe 'some class' do
	# some code
end
It Method
- Similar to other testing frameworks, we can use itto describe a test
- itis a single test
- we can have multiple itblocks inside adescribeblock
- itaccepts a- Stringas an argument- the string should describe what the test is doing (e.g. "returns true when given a positive number")
 
require_relative 'boat'
describe Boat do
  it 'should create boats' do
    expect(Boat.new).to be_a Boat
  end
end
Running a test
Run your test with rspec:
 rspec example_spec.rb
You should see something like this in your terminal as a result:
.
Finished in 0.00144 seconds (files took 0.06003 seconds to load)
1 example, 0 failures
Expect Method
- expectis used to expect a result from a test
- it marks an assertion that we expect to be true
describe Boat do
  it 'should create boats' do
    expect(Boat.new).to be_a Boat
  end
  it 'should have a name' do
    expect(Boat.new.name).to eq 'Boaty McBoatface'
  end
end
to Method
- use the tomethod to complete the assertion (e.g.expect(Boat.new).to be_a Boat)
- after towe can use a matcher to check for a specific result
Matchers
- Matchers are used to check for specific results
Common matchers:
- eq- checks for equality
- be_a- checks for a specific class
- be_empty- checks for an empty array
- be_truthy- checks for a truthy value
- be_falsey- checks for a falsy value
- include- checks if an array includes a specific value
Test-Driven Development
Let's add some methods on our Boat class and write some tests for them.
We are going to write our tests first, then write the code to make the tests pass.
describe Boat do
  it 'should create boats' do
    expect(Boat.new).to be_a Boat
  end
  describe '#allowed_aboard?' do   # describe block inside a describe block
  end
end
It is valid to nest describe blocks inside other describe blocks. This is useful for grouping tests together.
Notice the # before allowed_aboard?. This is a convention to indicate that we are testing an instance method.
Let's finish the test for the allowed_aboard? method:
describe Boat do
  it 'should create boats' do
    expect(Boat.new).to be_a Boat
  end
  describe '#allowed_aboard?' do
    it 'returns true if inventory includes a life jacket' do
      a_boat = Boat.new
      allowed = a_boat.allowed_aboard?(['life jacket', 'sun glasses'])
      expect(allowed).to be true
    end
  end
end
- the allowed_aboard?method takes an array of inventory as an argument
- returns trueif the inventory includes alife jacket.
- use the tomatcher to check if the result istrue
If we run this test we will get the following error:
rspec boat_spec.rb
.F
Failures:
  1) Boat#allowed_aboard? returns true if inventory includes a life jacket
     Failure/Error: allowed = a_boat.allowed_aboard?(['life jacket', 'sun glasses'])
     NoMethodError:
       undefined method `allowed_aboard?' for #<Boat:0x000000010298e420>
             allowed = a_boat.allowed_aboard?(['life jacket', 'sun glasses'])
                             ^^^^^^^^^^^^^^^^
     # ./boat_spec.rb:10:in `block (3 levels) in <top (required)>'
Finished in 0.00158 seconds (files took 0.06525 seconds to load)
2 examples, 1 failure
Failed examples:
rspec ./boat_spec.rb:8 # Boat#allowed_aboard? returns true if inventory includes a life jacket
This tells us:
- we have an undefined methodcalledallowed_aboard?for theBoatclass
Let's write the code to make this test pass:
class Boat
  def allowed_aboard?(inventory)
    inventory.include?('life jacket')
  end
end
We should also test out the false case:
describe Boat do
  it 'should create boats' do
    expect(Boat.new).to be_a Boat
  end
  describe '#allowed_aboard?' do
    it 'returns true if inventory includes a life jacket' do
      a_boat = Boat.new
      allowed = a_boat.allowed_aboard?(['life jacket', 'sun glasses'])
      expect(allowed).to be true
    end
    it 'returns false if inventory does not include a life jacket' do
      a_boat = Boat.new
      allowed = a_boat.allowed_aboard?(['sun glasses'])
      expect(allowed).to be false
    end
  end
end
Setting up a project for RSpec
group :development, :test do
  gem 'rspec-rails', '~> 5.1'
  gem 'net-smtp', require: false
  # ...
end
- Add the rspec-railsgem to yourGemfile
- Add the net-smtpgem to yourGemfile
- if you have a current /specfolder, remove itrm -rf spec