使用Capybara在测试之间保持用户在数据库中?

时间:2014-02-11 15:31:43

标签: ruby-on-rails ruby-on-rails-4 capybara rspec-rails

我的问题是我必须为每个单独的水豚测试创建一个新用户并登录。

以下是一个例子:

require 'spec_helper'

describe "users" do
  describe "user registration" do
    it "should create a new user and log in" do
      # Register a new user to be used during the testing process
      visit signup_path
      fill_in 'Email', with: 'testuser'
      fill_in 'Password', with: 'testpass'
      fill_in 'Password confirmation', with: 'testpass'
      click_button 'Create User'
      current_path.should == root_path
      page.should have_content 'Thank you for signing up!'
    end
  end

  describe "user login" do
    it "should log in" do

      # log in
      visit login_path
      fill_in 'Email', with: 'testuser'
      fill_in 'Password', with: 'testpass'
      click_button 'Log In'
      current_path.should == root_path
      page.should have_content 'Logged in!'
    end
  end
end

登录测试失败,因为该测试的数据库中不再存在该用户。

这可以通过将两者放在一个测试中来解决,但我认为这是不好的做法。

此外,我还有另一个文件,目前正在使用before_do在每个测试之间进行注册和登录,这看起来也很糟糕......你can see that code here

为了记录这是我的第一个rails应用程序,所以也许我试图以错误的方式做到这一点。我想尽可能地干掉它。

在需要用户登录的网页上使用capybara真的很糟糕吗?

1 个答案:

答案 0 :(得分:1)

我这样做了。

require "spec_helper"

  describe "Users" do
     subject { page }
     describe "User Registration" do
        before { visit signup_path }

        let(:submit) { "Sign up" }

        describe "with invalid information" do
           it "should not create a user" do
             expect { click_button submit }.not_to change(User, :count)
           end
        end

        describe "with valid information" do
           before do
             fill_in "Email",        with: "user@example.com"
             fill_in "Password",     with: "foobar12"
             fill_in "Password confirmation", with: "foobar12"
           end

           it "should create a user" do
              expect { click_button submit }.to change(User, :count).by(1)
           end

           describe "after registration" do
             before { click_button submit }
             it { should have_content 'Thank you for signing up!' }
           end

           describe "after registration signout and login" do
              let(:user) { User.find_by_email('user@example.com') }
              before do
                click_button submit 
                visit signout_path
                sign_in user     # sign_in is a method which u can define in your spec/support/utilities.rb . Define once and use at multiple places.
              end
              it { should have_content 'Logged In!' }
              it { should have_link('Logout') }
           end
        end
     end    
   end

#spec / support / utilities.rb

def sign_in(user)
  visit sign_path
  fill_in "Email",    with: user.email
  fill_in "Password", with: user.password
  click_button "Log in" 
end

您的每个describeit块都将在父级before块之后运行,这就是我们需要在上述测试用例中的每个块中单击click_button的原因。