RSpec command line

Given we have the following Person class:

class Person
def initialize(age:)
@age = age
end

def adult?
@age > 17
end
end
And equally simple test in the person_spec.rb file:

require ‘spec_helper’

RSpec.describe Person do
describe ‘#adult?’ do
it ‘returns false if the given person is less than 18 years old’ do
person = Person.new(age: 16)

  expect(person.adult?).to eq(false)
end

it 'returns true if the given person is more than 17 years old' do
  person = Person.new(age: 19)

  expect(person.adult?).to eq(true)
end

end
end
We can run it using the standard rspec command:

rspec spec/person_spec.rb
The custom output of the tests
When I talk or write about tests, I usually mention that tests are part of the code documentation. Sure, you can just open test files and look through them, but thanks to the –format option, you can run the test and receive an output that looks like documentation.

By default, the tests’ output consists of dots for passed tests, starts for pending tests, and F characters for those who failed. You can change this behavior by passing the –format option:

rspec spec/ –format documentation
Thanks to the above command instead of the default output:

..
You will receive the following format:

Person
#adult?
returns false if the given person is less than 18 years old
returns true if the given person is more than 17 years old
In the next paragraph, I will show you a cool combination with this option that will allow you to display the “documentation” only for the given method. And just in case you would need to save this piece of documentation for later – you can save the output in the file by using the –out option:

rspec spec/ –format documentation –out rspec_documentation.txt
Filtering tests by example name
The –example option allows you to run only those tests that are matching the given string. The argument is matched against the full description of the example. The full description is the concatenation of descriptions of the group, including any nested groups and contexts.

If you would like to run only those tests that test if the #adult? method returns true, you could do the following:

rspec –example ‘#adult? returns true`
With the combination of –format option, you can even get a list of cases when the method returns true:

rspec –example ‘#adult? returns true` –format documentation
In our case, the output will be the following:

Person
#adult?
returns true if the given person is more than 17 years old
You don’t even have to open the code editor to answer the question; cool, isn’t it?

Filtering tests by tag name
If you would like to tag some examples that belong to the given feature, you can quickly run them all at once by using the –tag option. Let’s assume that our spec belongs to the authentication feature:

RSpec.describe Person do
describe ‘#adult?’, feature: ‘authentication’ do
it ‘returns false if the given person is less than 18 years old’ do
person = Person.new(age: 16)

 expect(person.adult?).to eq(false)

end

it ‘returns true if the given person is more than 17 years old’ do
person = Person.new(age: 19)

 expect(person.adult?).to eq(true)

end
end
end
When you have many tests, and their execution takes much time, you don’t want to select manually all specs related to the feature you are working on. To run only tests related to authentication, you can use the following command:

rspec spec/ –tag feature:authentication
If would have cases where one spec belongs to more than one feature, than there is no need to worry; arrays of arguments are also supported:

require ‘./person’
require ‘spec_helper’

RSpec.describe Person do
describe ‘#adult?’ do
it ‘returns false if the given person is less than 18 years old’, feature: [‘authentication’, ‘other’] do
person = Person.new(age: 16)

 expect(person.adult?).to eq(false)

end

it ‘returns true if the given person is more than 17 years old’, feature: ‘authentication’ do
person = Person.new(age: 19)

 expect(person.adult?).to eq(true)

end
end
end
You can still use the –tag option as before and filter tests:

rspec spec/ –tag feature:authentication # will run two tests
rspec spec/ –tag feature:other # will run one test
Filtering tags with boolean value is also possible, and it’s even easier. If you usually mark slow tests like this:

it ‘returns false if the given person is less than 18 years old’, slow: true do
person = Person.new(age: 16)

expect(person.adult?).to eq(false)
end
You can run only slow tests by using a special syntax:

rspec spec/ –tag @slow
Which is a shortcut for –tag slow:true

You saw a few examples that let you filter the tests by their tags, but how about excluding some tests knowing their tag or tags? It’s as easy as adding ~ before the tag value:

rspec spec/ –tag [email protected]
The above command will run all specs except those marked as slow. Feel free to use other combinations of –tag with the exclude character.

Running specs… without running the tests
At first, it sounds a little bit weird, but yes, it’s possible to run tests without running them. It’s called a dry run, and you could meet this term before in the software development. The dry run means that you run the process, but it does not affect anything.

If you have a large tests codebase and you would like to see how many specs are there or how many are pending, you can perform a dry run that won’t trigger the tests, but the rspec will behave as we would run them:

rspec spec/ –dry-run
In the large codebase, the output could be the following:

Finished in 0.10594 seconds (files took 20.68 seconds to load)
1429 examples, 0 failures, 5 pending
Nice, it would be great to execute almost 1,5k of tests in less than one second. Another good example of –dry-run usage is the case where you would like to see the documentation for a given method but without running the tests:

rspec spec/ –format documentation –dry-run –example “#instance_method”
Failing fast
If you are working on fixing failures in the test suite, you will appreciate the –fail-fast option. If you look for a first failure and don’t want to continue after it appears, use the following command:

rspec spec/ –fail-fast
The RSpec won’t continue running tests after the first failure. If you want to stop after more than one failure, you can specify the number of failed tests after which the tests should be stopped:

rspec spec/ –fail-fast=6
By default, the RSpec won’t stop on the first failure and will continue running tests until all requested tests are executed.

Focusing on failures
If we are talking about the RSpec’s support for failing tests, it is worth mentioning the –only-failures option. If you are working on fixing failures, you can save the failures into a file and then, with the –next-failure option, jump to the next failing example after you fix the current one.

To make usage of –only-failures option, you have to change the RSpec’s config and specify the file where the library will store recent errors:

RSpec.configure do |c|
c.example_status_persistence_file_path = “failures.txt”
end
Now, when you execute your tests, RSpec will save failing tests in the failures.txt file:

example_idstatusrun_time
./spec/person_spec.rb[1:1:1]failed0.01228 seconds
./spec/person_spec.rb[1:1:2]failed0.00015 seconds
You can now run the first failing test:

rspec spec/ –next-failure
or run all failing tests:

rspec spec/ –only-failures
For those who deal with random failures
One more thing related to the failures. Sometimes when you run the whole test suite, one spec is failing, but when you execute only this one spec, it’s passing – this may be confusing, but it’s not something that the RSpec creators were not aware of.

With the –bisect option, RSpec will run your tests to find the minimal number of examples needed to reproduce the failure. With such information, it will be easier to find the place in the test where the data is overwritten, and the result of the test is different from the one received when one test is executed.