RSpec
There are many test harnesses for Ruby. RSpec is the most popular. It has inspired many imitators such as Jasmine for JavaScript and PHPSpec for PHP.
Getting RSpec
Install rspec using
gem install rspec
or if you prefer add it to your Gemfile and bundle.
You now have a new terminal command, rspec. Type:
rspec;
in a terminal to test your installation.
Writing a spec
RSpec is very easy to setup. Create a folder called spec in the same directory as your code. This is where your specs will live.
In the spec folder create a file called test_spec.rb. Place the following code in it:
describe "an example spec" do
it "passes" do
expect(true).to be(true)
end
end
run your specs with:
rspec spec/*
You should see a message like this, telling you the specs have passed:
Finished in 0.00105 seconds (files took 0.11919 seconds to load)
1 example, 0 failures
Testing some actual code
Let’s write an alarm clock function to wake us up in the morning. When we call it it’s going to give us a message: “Beep beep beep”. This will help us wake up.
def wake_me_up
"Beep beep beep"
end
Save this in a file called clock.rb
Now let’s write a spec for it. First we need to import our clock, then we call the code, then we say what the result should be:
require_relative '../clock'
describe "alarm clock" do
it "beeps" do
expect(wake_me_up).to eq('Beep beep beep')
end
end
Run this and verify it works
Test First
This is all well and good, but what about Test Driven Development (TDD). In this methodology we write the test first, watch it fail, then write code to make it pass.
Some-days I feel sleepy and I’d like to be woken with more force. I’d like my alarm clock to accept an optional parameter and wake me up more strongly.
First we write the spec
require_relative '../clock'
describe "alarm clock" do
it "beeps" do
expect(wake_me_up).to eq('Beep beep beep')
end
it "beeps louder" do
expect(wake_me_up(6)).to eq('Beep beep beep beep beep beep')
end
end
Now we run the spec and we see red:
1) alarm clock beeps
Failure/Error: expect(wake_me_up(6)).to eq('Beep beep beep beep beep beep')
ArgumentError:
wrong number of arguments (1 for 0)
# ./clock.rb:5:in `wake_me_up'
# ./spec/clock_spec.rb:16:in `block (2 levels) in <top (required)>'
Finished in 0.00161 seconds (files took 0.14819 seconds to load)
2 examples, 1 failure
Failed examples:
rspec ./spec/clock_spec.rb:15 # alarm clock beeps
Notice it’s telling us exactly what and where the problem is. Let’s write code to make our test pass.
def wake_me_up(i = 3)
("beep " * i).strip.capitalize
end
Run the test again and success, we have a passing test.
Many developers say they live for these moments of green. You may or may not love testing as much as this but regardless, a good suite of passing tests can give you piece of mind at the weekend and help you sleep better at night, knowing you have done a good job.
Exercise - Write some tests
Review the RSpec matcher documentation here:
https://www.relishapp.com/rspec/rspec-expectations/docs/built-in-matchers
In the section on blocks you wrote code to reverse the individual words in a string, but not the string itself, such that:
"Hello World";
becomes:
"olleH dlroW";
- Extract this code into a function and write a spec for it.
- Do the same for the gsub and inject exercises.