Integration testing with encrypted passwords
Unit tests and functional tests are essential tools, but they can’t exercise your browser-side Javascript/JQuery code, and that’s where some features on my website broke — to my great embarrassment — some time over the past few months. I updated many things — JQuery, Rails, JRuby, several JQuery plugins, my JQuery code, rails.js, replacing will_paginate with kaminari, etc. — before realizing that somewhere along the line some of my client-side Javascript had broken.
Last year, I did some integration testing using Capybara (previously Webrat), Cucumber, Selenium, RSpec, and FactoryGirl, but I never got very far because I always got stuck on how to test Devise, with its encrypted passwords, password salts, and confirmable module. Fixtures wouldn’t work because passwords are not stored directly in the database; encrypted versions of passwords are stored.
I’m happy to have finally gotten past that annoying hurdle after realizing FactoryGirl provides four different build strategies:
- “build()” creates an instance without saving it to the database
- “create()” creates and saves an instance to the database
- “attributes_for()” defines a set of valid attributes without creating an instance
- “stub()” creates an object with stubbed attributes
The solution to my problem is having FactoryGirl hand each test a valid set of attributes, which the test then uses twice: first, to create and save a user object, and, second, to log in as that user. (If you’re using the confirmable module, you’ll also want your test code to call “user.confirm!” before attempting to log in.)
One other problem that caused me much grief is that Capybara works with various engines, but you can’t mix syntaxes. This works:
get new_user_session_path
response.body.should include("Sign in")
And this works:
visit new_user_session_path
page.should have_content("Sign in")
But this will fail (and possibly cause you to tear your hair out, as I nearly did):
get new_user_session_path
page.should have_content("Sign in")
So, be careful not to mix-and-match!
Posted by James on Monday, June 20, 2011