Getting Started with RSpec testing in Ruby

Getting Started with RSpec testing in Ruby

Why RSpec

Table of contents

RSpec is a test framework for ruby that has grown in popularity and for good reason. Users of Ruby have an option of picking an equally capable framework called minitest that ships with rails by default. So why pick Rspec:

  • It reads like plain English making it easier to follow

  • Its easy syntax makes it a good documentation for the code

  • It comes fully featured out of the box and no need to install additional gems

Understanding rspec

Installing gem rspec is all you need to get started. After installation create a folder called spec (meaning specifications) in your project which will contain all the test files. In our case we can name our test file coffee_spec.rb. The syntax of rspec involves a describe block to group related tests together. This is followed by an it block which groups each test case .Inside the it block is where you check if the code does what is supposed to do by using expect keyword. Then run the tests by typing rspec in the terminal. Passing tests are green in color while failing tests are red. Let us see an example:

RSpec.describe 'An ideal cup of coffee' do   # describe block

    it 'is delicious' do    #First test starts here
     coffee = Coffee.new()  #Instantiation of Coffee class
     taste = coffee.taste
     expect(taste).to eq('delicious') #The result we expect
    end
end

As you can see the syntax reads like plain English. This test will fail with a red color of course because we do not have a coffee class which is what we should expect in test driven development. Lets say you also want to test the price of the coffee.

RSpec.describe 'An ideal cup of coffee' do

    it 'is delicious' do
     coffee = Coffee.new()
     taste = coffee.taste
     expect(taste).to eq('delicious')
    end

   it "costs one dollar" do   #Second test starts here
     coffee = Coffee.new()
     price = coffee.price
     expect(price).to eq(1)
   end
 end

Also note there are other many more matchers you can use i.e. expect(result).to_not be_nil, and you can read more here https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/. There is also some repetition as we are instantiating coffee on every test example which can be expensive. This can be avoided by using a helper method let just once at the beginning . It is also common to use a context block to be more concise when one test has several variations. For example we can test the price of coffee when black or white. Lets now implement everything we have learnt.

# Start of the Coffee class 
class Coffee
# Start of the taste method  
  def taste
    "delicious"
  end
# Start of the price method  
  def price(flavour)
    case flavour
    when "white"
      1
    when "black"
      0.8
    else
      raise ArgumentError, "Unknown flavour: #{flavour}"
    end
  end
end
# Start of the testing code
RSpec.describe "An ideal cup of coffee" do
  let(:coffee) { Coffee.new } # using let to avoid duplication
  it "is delicious" do
    taste = coffee.taste
    expect(taste).to eq("delicious")
  end
  context "when white coffee" do  #first context
    it "costs one dollar" do
      price = coffee.price("white")
      expect(price).to eq(1)
    end
  end
  context "when black coffee" do #second context
    it "costs 0.8 dollar" do
      price = coffee.price("black")
      expect(price).to eq(0.8)
    end
  end
  context "when  wrong flavour" do # third context
    it "raises an error" do
      expect { coffee.price("wrong") }.to raise_error(ArgumentError, "Unknown flavour: wrong")
    end
  end
end

Now the tests pass green. This is a basic example of how rspec works and how it makes testing a bliss. Happy coding!!

Lets connect on X https://twitter.com/allanmk01