You may want to read the section on RSpec Metadata before reading this section because, as it turns out, RSpec filtering is based on RSpec Metadata.
Imagine that you have a spec file and it contains two types of tests (Examples): positive functional tests and negative (error) tests. Let’s define them like this −
RSpec.describe "An Example Group with positive and negative Examples" do context 'when testing Ruby\'s build-in math library' do it 'can do normal numeric operations' do expect(1 + 1).to eq(2) end it 'generates an error when expected' do expect{1/0}.to raise_error(ZeroDivisionError) end end end
Now, save the above text as a file called ‘filter_spec.rb’ and then run it with this command −
rspec filter_spec.rb
You will see output that looks something like this −
.. Finished in 0.003 seconds (files took 0.11201 seconds to load) 2 examples, 0 failures
Now what if, we wanted to re-run only the positive tests in this file? Or only the negative tests? We can easily do that with RSpec Filters. Change the above code to this −
RSpec.describe "An Example Group with positive and negative Examples" do context 'when testing Ruby\'s build-in math library' do it 'can do normal numeric operations', positive: true do expect(1 + 1).to eq(2) end it 'generates an error when expected', negative: true do expect{1/0}.to raise_error(ZeroDivisionError) end end end
Save your changes to filter_spec.rb and run this slightly different command −
rspec --tag positive filter_spec.rb
Now, you will see output that looks like this −
Run options: include {:positive=>true} . Finished in 0.001 seconds (files took 0.11401 seconds to load) 1 example, 0 failures
By specifying --tag positive, we’re telling RSpec to only run Examples with the: positive metadata variable defined. We could do the same thing with negative tests by running the command like this −
rspec --tag negative filter_spec.rb
Keep in mind that these are just examples, you can specify a filter with any name that you want.
Formatters allow RSpec to display the output from tests in different ways. Let’s create a new RSpec file containing this code −
RSpec.describe "A spec file to demonstrate how RSpec Formatters work" do context 'when running some tests' do it 'the test usually calls the expect() method at least once' do expect(1 + 1).to eq(2) end end end
Now, save this to a file called formatter_spec.rb and run this RSpec command −
rspec formatter_spec.rb
You should see output that looks like this −
. Finished in 0.002 seconds (files took 0.11401 seconds to load) 1 example, 0 failures
Now run the same command but this time specify a formatter, like this −
rspec --format progress formatter_spec.rb
You should see the same output this time −
. Finished in 0.002 seconds (files took 0.11401 seconds to load) 1 example, 0 failures
The reason is that the “progress” formatter is the default formatter. Let’s try a different formatter next, try running this command −
rspec --format doc formatter_spec.rb
Now you should see this output −
A spec file to demonstrate how RSpec Formatters work when running some tests the test usually calls the expect() method at least once Finished in 0.002 seconds (files took 0.11401 seconds to load) 1 example, 0 failures
As you can see, the output is quite different with the “doc” formatter. This formatter presents the output in a documentation-like style. You might be wondering what these options look like when you have a failure in a test (Example). Let’s change the code in formatter_spec.rb to look like this −
RSpec.describe "A spec file to demonstrate how RSpec Formatters work" do context 'when running some tests' do it 'the test usually calls the expect() method at least once' do expect(1 + 1).to eq(1) end end end
The expectation expect(1 + 1).to eq(1) should fail. Save your changes and re-run the above commands −
rspec --format progress formatter_spec.rb and remember, since the “progress” formatter is the default, you could just run: rspec formatter_spec.rb. You should see this output −
F Failures: 1) A spec file to demonstrate how RSpec Formatters work when running some tests the test usually calls the expect() method at least once Failure/Error: expect(1 + 1).to eq(1) expected: 1 got: 2 (compared using ==) # ./formatter_spec.rb:4:in `block (3 levels) in <top (required)>' Finished in 0.016 seconds (files took 0.11201 seconds to load) 1 example, 1 failure Failed examples: rspec ./formatter_spec.rb:3 # A spec file to demonstrate how RSpec Formatters work when running some tests the test usually calls the expect() method at least once
Now, let’s try the doc formatter, run this command −
rspec --format doc formatter_spec.rb
Now, with the failed test, you should see this output −
A spec file to demonstrate how RSpec Formatters work when running some tests the test usually calls the expect() method at least once (FAILED - 1) Failures: 1) A spec file to demonstrate how RSpec Formatters work when running some tests the test usually calls the expect() method at least once Failure/Error: expect(1 + 1).to eq(1) expected: 1 got: 2 (compared using ==) # ./formatter_spec.rb:4:in `block (3 levels) in <top (required)>' Finished in 0.015 seconds (files took 0.11401 seconds to load) 1 example, 1 failure
rspec ./formatter_spec.rb:3 # A spec file to demonstrate how RSpec Formatters work when running some tests the test usually calls the expect() method at least once.
RSpec Formatters offer the ability to change the way test results display, it is even possible to create your own custom Formatter, but that is a more advanced topic.