Photo by Alex Holyoake

The most common way for me to fire up tests in any project, especially when I’m new to it and want to test what’s already covered, how much is covered, what passes and what fails is to run rspec in the terminal; this runs tests for all examples in the project.

During development, we usually don’t want to run the whole test suite. Most of us want to run only tests related to changes we’ve made to save time.

Here are several ways to run specific RSpec tests:

1. By File & Directory Names

Running tests by file their file or directory names is the most familiar way to run tests with RSpec. rspec selectively takes a file name (path) or a directory name, then runs the file or the contents of the directory, both. So you can do:

rspec spec/jobs to run only test found in the jobs directory.

rspec spec/jobs spec/services to run only test found in the jobs and services directory.

rspec spec/models/user_spec.rb to only run the tests in the user_spec.rb file.

rspec spec/jobs spec/models/user_spec.rb to run all tests from the jobs folder in addition to specs found in the user_spec.rb file.

2. By Sections of an Example Group

Henceforth, let’s use the spec file and class below as our test sample.

# person_spec.rb class Person attr_accessor :first_name , :last_name , :height , :eye_colour def initialize ( first_name , last_name , height = 160 , eye_colour = 'grey' ) @first_name = first_name @last_name = last_name @height = height @eye_colour = eye_colour end def local_greeting ( greeting ) greeting . to_s end end RSpec . describe 'Person' do before do @person = Person . new ( 'Emmanuel' , 'Hayford' ) end context 'identity' do it 'should tell first name' do expect ( @person . first_name ). to eq ( 'Emmanuel' ) end it 'should tell last name' do expect ( @person . last_name ). to eq ( 'Hayford' ) end end context 'physical features' do it 'should be able to tell height' do expect ( @person . height ). to eq ( 160 ) end it 'should be able to tell eye colour' do expect ( @person . eye_colour ). to eq ( 'grey' ) end end context 'culture' do it 'should be able to greet in local language' do local_greeting = @person . local_greeting ( 'Maakye' ) expect ( local_greeting ). to eq ( 'Maakye' ) end end end

RSpec easily allows picking one section (or several) of an example group to run, allowing us to run something like rspec person_spec.rb:21 where 21 is the exact line number of the section, we want to run. The line number could fall on any of these RSpec methods: describe , context , it or expect and RSpec will smartly run just that section. If the line falls on an empty line, RSpec will run the closest (from the top) it block of the test file. And if the blank line is the above all the test examples, then RSpec will just run all the tests!

We can also run a section of tests by doing rspec person_spec.rb[1:3] . The [x:y] format instructs RSpec to run the x th group (in our case we have just one group… which is everything inside the RSpec.describe 'Person' block) and the y th example block. So running rspec person_spec.rb[1:3] will run the 'culture' block. You can do multiple sections like rspec person_spec.rb[1:1,1:3] for example which will then run just the 'identity' and 'culture' blocks.

3. Through the Description of an Example

You can run a test like so rspec person_spec.rb -e "greet" ; this will run all examples/groups that have “greet” in their description. The -e flag is short for --example . It is worth noting, however, that this is case sensitive so rspec person_spec.rb -e "greet" and rspec person_spec.rb -e "Greet" won’t yield the same results.

Running rspec person_spec.rb -e "greet" -fd in on our spec file will return

Run options: include { :full_description => /greet/ } Person culture should be able to greet in local language Finished in 0.00088 seconds ( files took 0.09423 seconds to load ) 1 example , 0 failures

There’s only one example that has “greet” in its description.

4. By Focusing on an Example

This feature is handy if you’re working on just one test or a group that you’re working. To use this feature, you have to go an extra step with your configuration. The configuration in question is

RSpec . configure do | config | config . filter_run_when_matching focus: true end

In a typical Rails project, this might go in your spec_helper.rb file. Once this configuration is in place, you can add f to describe , context or it so it becomes fdescribe , fcontext or fit and RSpec will “focus” on that example/group. Doing

fit 'should tell height' do expect ( @person . height ). to eq ( 160 ) end

is equivalent to

it 'should tell height' , focus: true do expect ( @person . height ). to eq ( 160 ) end

5. By Running Only Failing Tests

RSpec has rspec file_name_spec.rb --only-failures , very handy when you’re only interested in running tests that fail so you can work on fixing them. But to keep track of which tests failed the last time you run the tests, RSpec needs yet another configuration that will tell it when to store information on which tests failed/passed.

This configuration should look like

RSpec . configure do | config | config . example_status_persistence_file_path = 'some_file.txt' end

If you’re working with Git, you might want to add some_file.txt to .gitignore .

It’s essential to run this file once without any flags to record the statuses of all examples – this is how the content looks like after we run our tests for the first time with some (deliberate) failures.

Once the first run has recorded the statuses of the tests, we can then run rspec person_spec.rb --only-failures to run just the failing tests and re-run after we’ve made changes to our code to see if we’ve been able to fix the failure we’re tracking, if it has, its status will change to “passed” in the file that we configured for RSpec to do the tracking.

6. By Running Failing Tests (One-At-A-Time)

If there are multiple failures with rspec person_spec.rb --only-failures from the above, you can do rspec person_spec.rb --next-failure to repeatedly run a single failure at a time. Neat!

7. By Tag Filtering

You can tag examples/groups with a hash (RSpec calls this “metadata”, the focus: true in the tests you saw above is a metadata example). The hash can contain arbitrary key/values of your choice. For example, let’s say we want to mark some tests as important. We can do so by altering our tests to add an important: true so it looks like the following:

RSpec . describe 'Person' do before do @person = Person . new ( 'Emmanuel' , 'Hayford' ) end context 'identity' , important: true do # 👈 it 'should tell first name' do expect ( @person . first_name ). to eq ( 'Emmanuel' ) end it 'should tell last name' do expect ( @person . last_name ). to eq ( 'Hayford' ) end end context 'physical features' , important: false do # 👈 it 'should be able to tell height' do expect ( @person . height ). to eq ( 160 ) end it 'should be able to tell eye colour' do expect ( @person . eye_colour ). to eq ( 'grey' ) end end context 'culture' , important: true do # 👈 it 'should be able to greet in local language' do local_greeting = @person . local_greeting ( 'Maakye' ) expect ( local_greeting ). to eq ( 'Maakye' ) end end end

With this change in place, we can run rspec person_spec.rb --tag important and expect to have only 3 examples running instead of 5.

Run options: include { :important => true } ... Finished in 0.00721 seconds ( files took 0.09502 seconds to load ) 3 examples , 0 failures

Armed with these I’m sure we can cumulatively save a lot of time, time that we can invest doing other things. Selectively picking tests you want will speed up development and I highly recommend doing this with real work.

Subscribe Powered By ConvertKit