Logging the user in before Capybara feature specs/system specs

by Jason Swett,

Logging in

If you’re building an app that has user login functionality, you’ll at some point need to write some tests that log the user in before performing the test steps.

One approach I’ve seen is to have Capybara actually navigate to the sign in page, fill_in the email and password fields, and hit submit. This works but, if you’re using Devise, it’s a little more complicated than necessary. There’s a better way.

The Devise docs have a pretty good solution. Just add this to spec/rails_helper:

RSpec.configure do |config|
  config.include Warden::Test::Helpers
end

Then, any place you need to log in, you can do login_as(FactoryBot.create(:user)).

Log in before each test or log in once before all tests?

One of my readers, Justin K, wrote me with the following question:

If you use Capybara to do system tests, how do you handle authentication? Do you do the login step on each test or do you log in once and then just try and run all of your system level tests?

The answer is that I log in individually for each test.

The reason is that some of my tests require the user to be logged in, some of my tests require that the user is not logged in, and other tests require that some specific type of user (e.g. an admin user) is logged in.

I do often put my login_as call in a before block at the top of a test file to reduce duplication, but that doesn’t mean only once for that set of files. A common misconception is that a before block will give a performance benefit by only running the code in the before block once. This is not the case. before is shorthand for before(:each) and any code inside it will get run before each individual it block. I never use before(:all) inside of individual tests because I want each test case to be as isolated as possible.

Leave a Reply

Your email address will not be published. Required fields are marked *