Getting started with rspec
Remarks#
RSpec is a BDD tool used to specify and test Ruby programs. It is used primarily to specify and test classes and methods, i.e. for unit testing.
The rspec gem is just a meta-gem which brings in the three parts of RSpec. Those three parts are also a way to structure this documentation.
- rspec-core provides RSpec’s way of structuring and running tests: the
rspec
command-line executable, thedescribe
,context
andit
methods, shared examples, etc. It is documented in the RSpec Core topic. - rspec-expectations provides RSpec’s support for expecting test results: the
expect
/to
expectation syntax and RSpec’s built-in matchers. (It also provides the deprecatedshould
expectation syntax.) It is documented in the RSpec Expectations topic. - rspec-mocks provides RSpec’s support for test doubles:
double
,allow
,expect
,receive
,have_received
, etc. It is documented in the RSpec Mocks topic.
There is also the rspec-rails gem, which extends RSpec with support for testing the types of classes used in Rails applications, and with support for writing feature specs (acceptance tests) which test the application from the user’s point of view.
Official documentation for RSpec and rspec-rails is here: https://www.relishapp.com/rspec
Installing RSpec
The most common way to install the RSpec gem is using Bundler. Add this line to your application’s Gemfile
:
gem 'rspec'
And then execute bundle
to install the dependencies:
$ bundle
Alternatively, you can install the gem manually:
$ gem install rspec
After installing the gem, run the following command:
rspec --init
This will create a spec
folder for your tests, along with the following config files:
- a
spec
directory into which to put spec files - a
spec/spec_helper.rb
file with default configuration options - an
.rspec
file with default command-line flags
A simple RSpec example
In greeter.rb (wherever that goes in your project):
class Greeter
def greet
"Hello, world!"
end
end
In spec/greeter_spec.rb:
require_relative '../greeter.rb'
RSpec.describe Greeter do
describe '#greet' do
it "says hello" do
expect(Greeter.new.greet).to eq("Hello, world!")
end
end
end
So our file structure looks like:
$ tree .
.
├── greeter.rb
└── spec
└── greeter_spec.rb
1 directory, 2 files
Output
$rspec greeter_spec.rb
Finished in 0.00063 seconds (files took 0.06514 seconds to load)
1 example, 0 failures
In RSpec terminology, the file is a “spec” of Greeter
and the it
block is an “example”. The line with expect
is an expectation. If the expectation is met, nothing happens and the test passes. If not, the test fails.
This example also shows that describe
blocks can be nested, in this case to convey that the greet
method is part of the Greet
class. The #
in #greet
is only a convention to show that greet
is an instance method (as opposed to ’.’ for a class method). RSpec doesn’t interpret the string at all, so you could use a different string or omit that describe
block entirely.