新手问题 使用 Capybara 跟直接使用浏览器有什么区别?

RainFlying · 2013年09月05日 · 最后由 zytedwards 回复于 2014年05月27日 · 4219 次阅读

使用 Capybara 提供的一些方法进行登录,比如

fill_in "Email", with: user.email
fill_in "Password", with: user.password
click_button "Sign in"

这个跟在浏览器里手动填表然后点击“Sign in”有什么区别?

更新一下问题。 问题来自于 Rails Tutorial 里的 Sample App。 http://ruby.railstutorial.org/chapters/updating-showing-and-deleting-users#sec-requiring_signed_in_users

spec/requests/authentication_pages_spec.rb 文件

require 'spec_helper'

describe "Authentication" do
  .
  .
  .
  describe "authorization" do
    .
    .
    .
    describe "as wrong user" do
      let(:user) { FactoryGirl.create(:user) }
      let(:wrong_user) { FactoryGirl.create(:user, email: "[email protected]") }
      before { sign_in user, no_capybara: true }

      describe "visiting Users#edit page" do
        before { visit edit_user_path(wrong_user) }
        it { should_not have_title(full_title('Edit user')) }
      end

      describe "submitting a PATCH request to the Users#update action" do
        before { patch user_path(wrong_user) }
        specify { expect(response).to redirect_to(root_url) }
      end
    end
  end
end

spec/support/utilities.rb


def sign_in(user, options = {})
  if options[:no_capybara]
    # Sign in when not using Capybara
    remember_token = User.new_remember_token
    cookies[:remember_token] = remember_token
    user.update_attribute(:remember_token, User.encrypt(remember_token))
  else
    visit signin_path
    fill_in "Email", with: user.email
    fill_in "Password", with: user.password
    click_button "Sign in"
  end
end

暂时先无视原文里 FactoryGirl 的错误,这个不是问题的所在。 把 before { sign_in user, no_capybara: true } 换成 before { sign_in user }, 浏览器里跳转是正常的,会跳到 root_url, 但是 rspec 里会有这样的错误

Failures:

1) AuthenticationPages authorization as wrong user submitting a PATCH request to the Users#update action Failure/Error: specify { expect(response).to redirect_to(root_url) } Expected response to be a redirect to http://www.example.com/ but was a redirect to http://www.example.com/signin. Expected "http://www.example.com/" to be === "http://www.example.com/signin". # ./spec/requests/authentication_pages_spec.rb:85:in `block (5 levels) in '

Finished in 5.81 seconds 76 examples, 1 failure, 3 pending

一个是手动,一个是自动就是区别 = =, 大量的行为测试手动吃不消啊

#1 楼 @showlovel 我之前也这么理解,但是 Rails Tutorial 里的一个测试,总是会抛错,但是手动在浏览器里执行的时候跳转是正常的。。。

#1 楼 @showlovel 我等会整理一下问题。

#3 楼 @RainFlying 那可能是测试写的有问题,因为写测试的时候你需要对请求——响应的全过程了然于心才不至于漏掉一些重要的步骤,而用浏览器的时候很多东西被隐藏在幕后了。

最大的区别应该是 capybara 默认不支持 javascript

我猜的哈,当你的 wrong user 登陆的时候,本身就登陆错误,所以不会 redirect 到 root, 会停留在 /signin

Expected response to be a redirect to http://www.example.com/ but was a redirect to http://www.example.com/signin.

所以才出现上面的错误

#6 楼 @showlovel 这个测试之前不是有一个 before { sign_in user },这个时候已经用 user 这个用户的信息完成登录吧,之后再发起 patch user_path(wrong_user), 这个时候已经处于登录状态了,但是并不是需要修改信息的用户,以下是 Controller 的代码,我怎么看都不能理解跳转到 Sign in 页面的情况,使用 before { sign_in user, no_capybara: true } 的时候就不会出现这样的问题。

class UsersController < ApplicationController
  before_action :signed_in_user, only: [:edit, :update]
  before_action :correct_user,   only: [:edit, :update]
  .
  .
  .
  def edit
  end

  def update
    if @user.update_attributes(user_params)
      flash[:success] = "Profile updated"
      sign_in @user
      redirect_to @user
    else
      render 'edit'
    end
  end
  .
  .
  .
  private

    def user_params
      params.require(:user).permit(:name, :email, :password,
                                   :password_confirmation)
    end

    # Before filters

    def signed_in_user
      redirect_to signin_url, notice: "Please sign in." unless signed_in?
    end

    def correct_user
      @user = User.find(params[:id])
      redirect_to(root_url) unless current_user?(@user)
    end
end

@RainFlying 把 signed_in? 换成 user_signed_in? 试试?

我也在跟着 Rails Tutorial 学习,出现这个情况是因为测试中用了get/post/patch/put,cookie 带不过去,如:

before { get edit_user_path(wrong_user) }

如果换成 visit,cookie 就能带过去,就不会redirect_to signin_url了,但具体我也说不清,仅供参考。

bjtugun rspec 和 capybara 的 cookies 是不同的 提及了此话题。 04月03日 10:57
需要 登录 后方可回复, 如果你还没有账号请 注册新账号