RSpec Testing Framework
RSpec is an automated TDD framework for Ruby. It is a domain specific language(DSL) which means it has its own syntax and keywords aside from Ruby itself.
The general workflow of RSpec is “ Given .. When .. Then .. ”.
An Example of this can be projected on a user story as follow:
Given user isn’t logged in. (the context)
When he visited login page. (the event)
Then he sees a page with login form. (the expectation)
Configuration
Configuring RSpec is optional most likely it is about appearance like having a colored output in the terminal versus a non-colored one, having a documented output with details or a simple output.
All these are flags that can be easily found using the “rspec --help” command
for example: adding the “-- no-color” flag in the .rspec file will force the output to be colorless.
The initial setup of RSpec can be done using the command “rspec --init”.
This will create a .rspec config file in the project directory.
A spec folder to contain the specs.
A spec_helper file inside of spec folder. (This will be included in all specs. If there is some global code needed in many spec files, here is a good place for it).
General layout of a spec
First we require the files we need, either it’s a class that we are going to test or helper file/module.
The describe keyword is the wrapping for the test suite, usually it is followed by a string or a className that this file has access to. As shown above multiple describe blocks can be nested inside each other.
The context keyword is a smaller wrapping block to provide more structure to the tests. It is used to identify the tests when the class is in a certain context.
The it keyword is the smallest wrapping block. Inside resides a test for a very specific case regarding some context and a className that is expected to behave in a certain fashion.
A good hint is to make your spec file English-readable, for example if it is a Car spec then the file is describing a Car. Try to make the pronoun “it” in your examples refer to Car. So to write a test asserting that Car responds to :wheels.
it “allows reading for wheels attribute” do .. end
Skipping Tests
using an ‘x’ before “it” or “describe” (It will become “xit”/“xdescribe”) will skip the test.
Also using skip(“needs expectation”) in the beginning of an “it” block will skip it.
Removing the do..end block will make the test pending.
Matchers
All the tests will consist of some logic that uses the method or class being tested and comparing its result with an expected value(that represent our target behavior).
For this purpose RSpec offers matchers that help in comparing values.
There are some types of matchers and examples for them:
- Equivalence matchers:
- Truthiness matchers:
Note: ‘0’ isn’t considered false in ruby
- Numeric comparison:
- Collections matchers:
They also work on hashes, strings.
- Observation matchers:
These are matchers that allow you to run a block of code and observe the effect of this block on some value.
Note: The {} block can be replaced with a do .. end block.
- Predicate matchers:
They are dynamically-defined matchers that make code more readable. Developer defines a method for instance called “visible?”. RSpec allows developer to use “be_visible” as a matcher.
- Respond Matchers:
makes sure that a class responds to a member / method call.
make sure a function is called with certain values.
Note: with can be called with any_args can be used if we want the arguments to be flexible.
- Regex Matcher:
Using regular expressions will be a powerful asset.
At the end, RSpec matchers are documented here on the site.
Hooks and Pre-setups
Some tests need setup before they can run, for example: declaring a variable, opening a file, connecting to a database. This is what hooks provide.
We can provide a block to be executed once before each test or once before the whole suite.
RSpec provides an implicit declaration of the class being tested if provided. This can be accessed using subject keyword.
Shared Examples
keeping code DRY is a best practice. Tests being code also, keeping them DRY will make our life easier.
When tests share common code, we can make a shared_example file and include it in different files.
An example on this will be APIs in Ruby on Rails.
Doubles / Stubs
Stands for another object, pre-programmed to receive a definite input and responds in a definite fashion.