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