Rubocop-rspec configuration
We added rubocop-rspec
to our Tramway gem. This is the first time I have used these special linter rules for RSpec.
Here is my `rubocop-rspec` configuration file with explanations of every rule.
# Single exception tests sounds good, but in practise it becomes a huge problem. Test examples run too many times and the whole test process becomes slow.
# Moreover, remember about `and` function that we can use. `expect(page).to have_css(css_1).and have_css(css_2)`
RSpec/MultipleExpectations:
Max: 3
# Let's see at this file https://github.com/Purple-Magic/tramway/blob/main/spec/helpers/navbar_helper_spec.rb
# 3 nested groups is not enough, cause we have levels `className` -> `functionName` -> `successOrFailure` -> `certain_case`. It should be 4 at least
RSpec/NestedGroups:
Max: 4
# According to expectations count. Let's imagine that we need 3 expectations in one test and also we need one line to make `service.call` or stuff like that. 3 * 3 + 1 = 10
RSpec/ExampleLength:
Max: 10
# I love this kind of expression `expect(form_class).to receive(:new).with(object).and_return(form_object)`, because it's short
RSpec/StubbedMock:
Enabled: false
Single / Multiple exceptions tests
RSpec/MultipleExpectations:
Max: 3
Single exception tests sound good, but it becomes a huge problem in practice. Test examples run too many times and the whole test process becomes slow.
Of course, we have and
method that allows us to do this:
expect(page).to have_css(css_1).and have_css(css_2)
And I love this method and use it. But in time we have issues with test running duration the idea of merging single-expectation tests into multiple expectations tests comes first or second.
So, it’s a good idea to limit test expectations by 3.
Nested groups
RSpec/NestedGroups:
Max: 4
Let’s see at Tramway Navbar spec file.
# frozen_string_literal: true
require 'support/view_helpers'
describe Tramway::Helpers::NavbarHelper, type: :view do
before do
described_class.include ViewHelpers
view.extend described_class
end
let(:title) { Faker::Company.name }
describe '#tramway_navbar' do
context 'with success' do
let(:left_items_css) { 'nav .flex ul.flex.items-center.space-x-4' }
let(:right_items_css) { 'nav ul.flex.items-center.space-x-4' }
context 'with title checks' do
it 'renders navbar with title and default link' do
fragment = view.tramway_navbar(title:)
expect(fragment).to have_content title
expect(fragment).to have_css "a[href='/']"
end
end
end
end
end
We have groups that should be in one file:
Tramway::Helpers::NavbarHelper -> #tramway_navbar -> with success -> with title checks
- Tramway::Helpers::NavbarHelper is a class name.
- #tramway_navbar — method name
- with success — group of cases
- with title checks — attribute-specific cases
Let’s talk about these rules or another in the comments :)