Skip to content

Instantly share code, notes, and snippets.

@kidlab
Last active November 23, 2018 07:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kidlab/bb139bf828b806d170a9774ecf21b11d to your computer and use it in GitHub Desktop.
Save kidlab/bb139bf828b806d170a9774ecf21b11d to your computer and use it in GitHub Desktop.
RSpec Best Practices

Standardize your code first

gem install fasterer
fasterer
  • Rubocop Performance is another good document. We can consider enabling Performance in .rubocop.yml as well.

Then, standardize your specs

There are a lot of useful tips you can follow in test-prof document. The main idea: avoid unnecessary database manipulation.

  • Use build_stubbed as much as possible if you don't need real ActiveRecord objects or DB queries.
  • Use let_it_be as much as possible to avoid unnecessary object creation. let_it_be is basically a wrapper around before_all
  • Aggregate the assertions together in a spec example (see more):
# slow
it { is_expected.to be_success }
it { is_expected.to have_header('X-TOTAL-PAGES', 10) }
it { is_expected.to have_header('X-NEXT-PAGE', 2) }
its(:status) { is_expected.to eq(200) }

# fast
it 'returns the second page' do
  is_expected.to be_success
  is_expected.to have_header('X-TOTAL-PAGES', 10)
  is_expected.to have_header('X-NEXT-PAGE', 2)
  expect(subject.status).to eq(200)
end

Why? Because whenever RSpec runs an example likes it { is_expected.to be_success } it runs setup hooks (let, let!, before) again. And after an example is finished, it tears down the context (run after hooks and clean up database, etc.) to keep the environment clean.

By grouping the same assertions into one example, all of those setup and teardown hooks are run once.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment