-
Notifications
You must be signed in to change notification settings - Fork 0
Step09: Setting Up the Testing Environment
Note: You should already have rspec installed at this point Inspired by Ryan Bates' Railscasts on Testing - #275 and #413
-
Make sure you first run
$ rake db:test:prepareif you haven't already. Otherwise, the tests will not be able to access the database. Also run$ bundle binstubs rspec-coreto create a binstub file to use to run our model specs. -
Initialize Guard for rspec:
$ guard init rspec. This adds rspec-guard to the guardfile for watching changes to our specs. -
In a new tab, run
$ guardto start up guard. -
Enable capybara in rspec by requiring it at the top of
spec/spec_helper.rb:require 'capybara/rspec'. -
Remove the fixture path since we won't be using it:
config.fixture_path = "#{::Rails.root}/spec/fixtures" ```
-
You should already have a factories/ directory inside of spec/ and a users.rb file inside of that. If you don't, create these now (you must have Factory Girl installed). Inside of
spec/factories/users.rbcreate a User factory as follows:FactoryGirl.define do factory :user do name 'Test User' email 'test@example.com' password 'password55' password_confirmation 'password55' confirmed_at Time.now # use only if implementing Confirmable end end
-
Configure Devise Test Helpers in
spec_helper.rbinside of theRspec.configure do |config|block withconfig.include Devise::TestHelpers, :type => :controllersee here for more info. -
Also add database cleaners to the same file to ensure a clean slate during tests (See the database_cleaner gem for more info):
config.before(:suite) do DatabaseCleaner.strategy = :truncation end config.before(:each) do DatabaseCleaner.start end config.after(:each) do DatabaseCleaner.clean end ```
-
Create a
controller_macros.rbfile inside of spec/support and add the following:
module ControllerMacros def login_user before(:each) do @request.env["devise.mapping"] = Devise.mappings[:user] user = FactoryGirl.create(:user) sign_in user end end end ```
-
Add your new Controller Macro to
spec_helpers.rbjust under your Devise Test Helpers configuration:config.extend ControllerMacros, :type => :controller -
To test our Devise Test Helpers we'll need to create a users controller:
$ rails g controller users index show --skip-stylesheets --skip-javascriptsand addbefore_filter :authenticate_user!tousers_controller.rb. -
Now we can create our first set of tests in
spec/controllers/users_controller_spec.rb:
require 'spec_helper'
describe UsersController do login_user
it "should have a current_user" do subject.current_user.should_not be_nil end
it "should get index" do # Note, erails 3.x scaffolding may add lines like get :index, {}, valid_session # the valid_session overrides the devise login. Remove the valid_session from your specs get 'index' response.should be_success end end ```
These tests should be passing (check that this is the case in your guard tab in terminal).
-
Next, we add tests for the User model in
spec/models/user_spec.rb. These tests are largely taken from Daniel Kehoe's excellent RailsApps example application using Devise, CanCan, and Bootstrap.
require 'spec_helper'
describe User do before(:each) do @user_attrs = { :name => "Example User", :email => "user@example.com", :password => "password55", :password_confirmation => "password55", :confirmed_at => Time.now } end
it "should create a new user given a valid attribute" do User.create!(@user_attrs) end
it "should require an email address" do blank_email_user = User.new(@user_attrs.merge(:email => "")) blank_email_user.should_not be_valid end
it "should accept valid email addresses" do addresses = %w[user@foo.com THE_USER@foo.bar.org first.last@foo.jp] addresses.each do |address| valid_email_user = User.new(@user_attrs.merge(:email => address)) valid_email_user.should be_valid end end
it "should reject invalid email addresses" do addresses = %w[user@foo,com user_at_foo.org example.user@foo.] addresses.each do |address| invalid_email_user = User.new(@user_attrs.merge(:email => address)) invalid_email_user.should_not be_valid end end
it "should reject duplicate email addresses" do User.create!(@user_attrs) user_with_duplicate_email = User.new(@user_attrs) user_with_duplicate_email.should_not be_valid end
it "should reject email addresses identical up to case" do upcased_email = @user_attrs[:email].upcase User.create!(@user_attrs.merge(:email => upcased_email)) user_with_duplicate_email = User.new(@user_attrs) user_with_duplicate_email.should_not be_valid end
describe "passwords" do it "should have a password and password_confirmation attributes" do @user = User.new(@user_attrs) @user.should respond_to(:password) @user.should respond_to(:password_confirmation) end end
describe "password validations" do it "should require a password" do User.new(@user_attrs.merge(:password => "", :password_confirmation => "")). should_not be_valid end
it "should require a matching password confirmation" do
User.new(@user_attrs.merge(:password_confirmation => "invalid")).
should_not be_valid
end
it "should reject short passwords" do
short = "a" * 5
hash = @user_attrs.merge(:password => short, :password_confirmation => short)
User.new(hash).should_not be_valid
end
end
describe "password encryption" do before(:each) do @user = User.create!(@user_attrs) end
it "should have an encrypted password attribute" do
@user.should respond_to(:encrypted_password)
end
it "should set the encrypted password attribute" do
@user.encrypted_password.should_not be_blank
end
end end ```
-
Finally, we're ready for our first test-driven test. Add the following to
spec/controllers/users_controller_spec.rb:
it "should not get index" do subject.current_user.destroy get 'index' response.should_not be_success end ```
It should not be passing! This is because we aren't actually authorizing users yet. Anyone can access any page. In the next section, we'll add in this functionality using CanCan and Rolify.