Keeping my integration specs DRY

Hi Group,

I’m finally taking the time to implement tests in some of my old apps.
I’m using Rails 2.3.5, Rspec 1.3.1, Rspec-rails 1.3.3, and capybara.

Here’s an example of my first test, but I’m wondering how I setup the
login routine so I can use it in future specs without repeating the
method. Some sort of - before.each (:login)

Can someone explain best practices for integration tests and if you’re
generous a simple code example.

require ‘spec_helper’

describe “Users” do
before(:each) do
@user = Factory(:user)
end

it “login” do
visit login_path
fill_in :login, :with => @user.email
fill_in :password, :with => @user.password
click_button “login_button”
page.has_content?(“Logged in successfully”)
end

it “creat profile” do
visit new_social_profile_path
end

end

On Fri, Jul 22, 2011 at 1:50 PM, internetchris [email protected]
wrote:

generous a simple code example.
visit login_path
end


rspec-users mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/rspec-users

Just put all of it in a method:

def login(user)
visit login_path
fill_in :login, :with => user.email
fill_in :password, :with => user.password
click_button “login_button”
end

before(:each) { login }

You can put the method in spec/support (and require it in spec_helper),
or,
define it in spec_helper

Here’s an example of my first test, but I’m wondering how I setup the
login routine so I can use it in future specs without repeating the
method. Some sort of - before.each (:login)
You can use shared examples…

shared_examples_for “any page requiring authentication” do
fill_in :login, :with => @user.email
fill_in :password, :with => @user.password
click_button “login_button”
page.has_content?(“Logged in successfully”)
end

Then in your specs you can do:

describe User do
it_behaves_like “any page requiring authentication”
end

Patrick J. Collins
http://collinatorstudios.com

On Jul 26, 2011, at 12:51 AM, Patrick J. Collins wrote:

end

Then in your specs you can do:

describe User do
it_behaves_like “any page requiring authentication”
end

You can use shared content, but what you have here ^^ doesn’t work as
written. The scope in the shared_examples_for block is an example group
scope, not an example scope, so methods like fill_in and click_button
are not available. You’d want to wrap them in a before block. Also,
page.has_content?(…) will return true or false, but will not act like
an expectation (i.e. RSpec won’t care which it returns).

Here are a couple of ways you could do this that will work as Chris
expects:

shared_context “logged in” do
let(:user) { Factory(:user) }
before do
fill_in :login, :with => user.email
fill_in :password, :with => user.password
click_button “login_button”
end
end

describe ArticlesController do
include_context “logged in”
describe “GET edit” do
it “does something” do
# here the shared before hook has already run
# and you have access to the user generated
# by the let declaration.
end
end
end

This assumes you only want one user. It’s simple and clean, without
confusing indirection or parameterization. On the other extreme you
could do this:

shared_context “logged in” do
before do
visit new_session_path
fill_in :login, :with => user.email
fill_in :password, :with => user.password
click_button :submit
end
end

shared_context “admin” do
let(:user) { Factory(:admin_user) }
include_context “logged in”
end

shared_context “staff” do
let(:user) { Factory(:staff_user) }
include_context “logged in”
end

RSpec.configure do |conf|
conf.alias_it_should_behave_like_to :logged_in_as
end

describe “Articles” do
describe “GET index” do
logged_in_as “admin” do
it “does something” do
# …
end
end
logged_in_as “staff” do
it “does something else” do
# …
end
end
end
end

The output from this looks like:

ArticlesController
GET index
logged in as admin
does something
logged in as staff
does something else

Both of these approaches keep things explicit. You can also do a more
implicit approach, like this:

RSpec.configure do |c|
c.before(:each, :type => :request) do
@user = Factory(:user)
visit new_session_path
fill_in :login, :with => @user.email
fill_in :password, :with => @user.password
click_button :submit
end
end

describe “Articles” do
describe “GET index” do
it “does something” do
# …
end
end
end

Here you don’t see any evidence in the example that you’re logging in.
Less typing, but less clarity. I’d avoid this approach myself, but it is
another option for you.

HTH,
David