title: Rails Tutorial: RSpec test decoupling
body: <p>I'm trying to do <a href="http://ruby.railstutorial.org/book/ruby-on-rails-tutorial#sec-sign_in_out_exercises">Exercise 2 of Chapter 8.5</a> in Michael Hartl's <a href="http://ruby.railstutorial.org/book/ruby-on-rails-tutorial">Ruby on Rails Tutorial</a>. The exercise is as follows: </p>
  
  <p>Following the example in Section 8.3.3, go through the user and authentication request specs (i.e., the files currently in the spec/requests directory) and define utility functions in spec/support/utilities.rb to decouple the tests from the implementation. Extra credit: Organize the support code into separate files and modules, and get everything to work by including the modules properly in the spec helper file.</p>
  
  <p>Example 8.3.3: utilities.rb</p>
  
  <pre><code>include ApplicationHelper
  
  def valid_signin(user)
    fill_in "Email",    with: user.email
    fill_in "Password", with: user.password
    click_button "Sign in"
  end
  
  RSpec::Matchers.define :have_error_message do |message|
    match do |page|
      page.should have_selector('div.alert.alert-error', text: message)
    end
  end
  </code></pre>
  
  <p>The defined <code>valid_signin(user)</code> function is used in the following block of <code>authentication_pages_spec.rb</code> and works fine.</p>
  
  <pre><code>describe "with valid information" do
      let(:user){FactoryGirl.create(:user)}
      before { valid_signin(user) }
  
      it { should have_selector('title', text: user.name) }
      it { should have_link('Profile', href: user_path(user)) }
      it { should have_link('Sign out', href: signout_path) }
      it { should_not have_link('Sign in', href: signin_path) }
  
      describe "followed by signout" do
          before { click_link "Sign out" }
          it { should have_link('Sign in') }
      end
  end
  </code></pre>
  
  <p>So with this example I set about to create my own named <code>valid_signup(user)</code>:</p>
  
  <pre><code>def valid_signup(user)
      fill_in "Name",         with: user.name
      fill_in "Email",        with: user.email
      fill_in "Password",     with: user.password
      fill_in "Confirmation",         with: user.password_confirmation
  end
  </code></pre>
  
  <p>I'm using this block in <code>user_pages_spec.rb</code> like this:</p>
  
  <pre><code>describe "with valid information" do
    let(:user){FactoryGirl.create(:user)}
    before { valid_signup(user) }
  
    it "should create a user" do
      expect { click_button submit }.to change(User, :count).by(1)
    end
  
    describe "after saving the user" do
      before { click_button submit }
      let(:user) { User.find_by_email(user.email) }
  
      it { should have_selector('title', text: user.name) }
      it { should have_selector('div.alert.alert-success', text: 'Welcome') }
      it { should have_link('Sign out') }
    end
  end
  </code></pre>
  
  <p>It doesn't work. Spork/Guard reports these errors:</p>
  
  <pre><code>Failures:
  
    1) UserPages signup with valid information should create a user
       Failure/Error: expect { click_button submit }.to change(User, :count).by(1)
         count should have been changed by 1, but was changed by 0
       # ./spec/requests/user_pages_spec.rb:46:in `block (4 levels) in '
  
    2) UserPages signup with valid information after saving the user 
       Failure/Error: before { valid_signup(user) }
       NoMethodError:
         undefined method `name' for nil:NilClass
       # ./spec/support/utilities.rb:10:in `valid_signup'
       # ./spec/requests/user_pages_spec.rb:43:in `block (4 levels) in '
  
    3) UserPages signup with valid information after saving the user 
       Failure/Error: before { valid_signup(user) }
       NoMethodError:
         undefined method `name' for nil:NilClass
       # ./spec/support/utilities.rb:10:in `valid_signup'
       # ./spec/requests/user_pages_spec.rb:43:in `block (4 levels) in '
  
    4) UserPages signup with valid information after saving the user 
       Failure/Error: before { valid_signup(user) }
       NoMethodError:
         undefined method `name' for nil:NilClass
       # ./spec/support/utilities.rb:10:in `valid_signup'
       # ./spec/requests/user_pages_spec.rb:43:in `block (4 levels) in '
  </code></pre>
  
  <p>The errors seem to suggest the user.name in my <code>valid_signup(user)</code> function in <code>utilities.rb</code> isn't defined, but I don't see any reason why. I've restarted Guard several times, and did a <code>rake db:test:prepare</code> to make sure the testing db (using postgresql) was in order.</p>
  
  <p>Here's my <code>factories.rb</code> for completeness:</p>
  
  <pre><code>FactoryGirl.define do
      factory :user do
          name    "Example User"
          email   "user@example.com"
          password    "foobar"
          password_confirmation   "foobar"
      end
  end</code></pre>
  
  <p>Before I continue to try and decouple more of the testing suite I'd very much like to solve this error and, more importantly, understand the reason for it.</p>
  
  <p><strong>EDIT</strong></p>
  
  <p>I've tried your tips, and edited the function in <code>user_pages_spec.rb</code> as follows:</p>
  
  <pre><code>describe "with valid information" do
        before { valid_signup(user) }
  
        it "should create a user" do
          expect { click_button submit }.to change(User, :count).by(1)
        end
  
        describe "after saving the user" do
          before { click_button submit }
          let(:user) { User.find_by_email('user@example.com') }
  
          it { should have_selector('title', text: user.name) }
          it { should have_selector('div.alert.alert-success', text: 'Welcome') }
          it { should have_link('Sign out') }
        end
      end</code></pre>
  
  <p>Since I removed <code>let(:user){FactoryGirl.create(:user)}</code> from the function I guessed there was no longer a user created in the function so I needed to define <code>valid_signup(user)</code> as such as the <code>user</code> variable for <code>valid_signup</code> was no longer being filled by FactoryGirl:</p>
  
  <pre><code>def valid_signup(user)
      fill_in "Name",     with: "Example User"
      fill_in "Email",    with: "user@example.com"
      fill_in "Password", with: "foobar"
      fill_in "Confirmation", with: "foobar"
  end</code></pre>
  
  <p>This didn't work and gave me the following errors:
  <pre><code>Failures:</p>
  
  <p>1) UserPages signup with valid information should create a user
       Failure/Error: before { valid_signup(user) }
       NameError:
         undefined local variable or method <code>user' for #&lt;RSpec::Core::ExampleGroup::Nested_5::Nested_3::Nested_2:0x007fdafc5088c0&gt;
       # ./spec/requests/user_pages_spec.rb:42:in</code>block (4 levels) in '</p>
  
  <p>2) UserPages signup with valid information after saving the user 
       Failure/Error: it { should have_selector('title', text: user.name) }
       NoMethodError:
         undefined method <code>name' for nil:NilClass
       # ./spec/requests/user_pages_spec.rb:52:in</code>block (5 levels) in '</pre></code></p>
  
  <p>I also tried running the test with <code>valid_signup(user)</code> the way I used to have it before (with <code>user.name, user.email, user.password, user.password_confirmation</code>, which didn't work either, with errors:</p>
  
  <pre><code>Failures:
  
    1) UserPages signup with valid information should create a user
       Failure/Error: before { valid_signup(user) }
       NameError:
         undefined local variable or method `user' for #
       # ./spec/requests/user_pages_spec.rb:42:in `block (4 levels) in '
  
    2) UserPages signup with valid information after saving the user 
       Failure/Error: it { should have_selector('title', text: user.name) }
       NoMethodError:
         undefined method `name' for nil:NilClass
       # ./spec/requests/user_pages_spec.rb:52:in `block (5 levels) in '</code></pre>
  
  <p>Next I tried running it without passing variables in <code>user_pages_spec.rb</code>: <code>before { valid_signup() }</code> and without a variable in the function in <code>utilities.rb</code>:</p>
  
  <pre><code>def valid_signup()
      fill_in "Name",     with: "Example User"
      fill_in "Email",    with: "user@example.com"
      fill_in "Password", with: "foobar"
      fill_in "Confirmation", with: "foobar"
  end</code></pre>
  
  <p>This returned:</p>
  
  <pre><code>Failures:
  
    1) UserPages signup with valid information should create a user
       Failure/Error: before { valid_signup(user) }
       NameError:
         undefined local variable or method `user' for #
       # ./spec/requests/user_pages_spec.rb:42:in `block (4 levels) in '
  
    2) UserPages signup with valid information after saving the user 
       Failure/Error: it { should have_selector('title', text: user.name) }
       NoMethodError:
         undefined method `name' for nil:NilClass
       # ./spec/requests/user_pages_spec.rb:52:in `block (5 levels) in '</code></pre>
  
  <p>Still no closer to the answer. I might be overlooking something simple. No clue what though. I got what I first did wrong though: I just thought FactoryGirl was a way to create variables, and I didn't know it actually did something to my test database.</p>