1

奇怪的问题。

我正在尝试使用 Capybara 和 RSpec 测试登录,但似乎 Capybara 填写了错误的字段,因此登录的用户未经过身份验证。

我使用 FactoryGirl 创建了测试用户:

#factories.rb

FactoryGirl.define do

    #...

    factory :user do
        name "guest"
        password "pwordtest"
        password_confirmation "pwordtest"
    end

end

然后我写了以下测试(其中有很多“放置”的东西来调试这个问题):

#posts_spec.rb

describe "Valid post submission" do

 it "should log in a user and let him make a post" do
  User.destroy_all
  visit '/access' #My Login page
  user = FactoryGirl.create(:user)
  puts "name"
  puts user.name
  fill_in :name, with: "guest" # I did these literally to make sure FactoryGirl wasn't the problem.
  fill_in :password, with: "pwordtest"
  click_on "Log In"
  assert User.count == 1
  puts "authing test"
  current_path.should eq(new_post_path)
 end
#...
end

在我的会话控制器中(更多调试):

def create
    user = User.find_by_name(params[:name])
    puts "all"
    puts params
    puts "pre-inspect"
    puts user.inspect
    if user && user.authenticate(params[:password])
        session[:user_id] = user.id
      puts "In IF"
        redirect_to new_post_path
    else
        flash.now[:error] = "Invalid password/username combo."
      puts "there"
        render 'new' 
    end
  end

当我尝试运行测试时,出现以下错误:

name
guest
all
{"utf8"=>"✓", "name"=>"pword", "password"=>"", "commit"=>"Log In", "action"=>"create", "controller"=>"sessions"}
pre-inspect
nil
there
authing test
F

Failures:

  1) Posts Valid post submission should log in a user and let him make a post
     Failure/Error: current_path.should eq(new_post_path)

       expected: "/posts/new"
            got: "/sessions"

       (compared using ==)
     # ./spec/requests/posts_spec.rb:28:in `block (3 levels) in <top (required)>'

换句话说,我的调试提示表明 FactoryGirl 用户很好,但不知何故,Capybara 未能将这些值分配给正确的字段,因此参数(在调试打印中的“全部”之后)被分配为“pword”作为name 和 "" 作为密码,而不是 "guest" 作为名称和 "pword" 作为密码。因此,测试用户未通过身份验证,并且会话未启动。这特别奇怪,因为这些字段的名称肯定是正确的:

#sessions/new.html.erb

<div class="center_login">
    <h1>Log In</h1>
    <%= form_tag sessions_path do %>
      <div class="field">
        <%= label_tag :name %>
        <%= text_field_tag :name, params[:name] %><br />
      </div>
      <div class="field">
        <%= label_tag :password %>
        <%= password_field_tag :password %><br />
      </div><br>
      <div class="actions"><%= submit_tag "Log In", class: "btn" %></div>
    <% end %>
</div>

知道发生了什么吗?我和另外两个人搞砸了一个小时+,就是想不通。

编辑——应该提到的是,当我作为一个真实的人浏览网站时,这一切都很完美。如,我在名称字段中输入的用户名和我在密码字段中输入的密码对应于数据库中的那些,并且我登录很好。因此,我怀疑某些 Capybara 未能填写正确的内容是错误的。

编辑 2——根据请求,以下一项测试的 Test.log 输出:

Connecting to database specified by database.yml
  [1m[36m (0.4ms)[0m  [1mbegin transaction[0m
Started GET "/posts/new" for 127.0.0.1 at 2013-02-14 07:29:55 -0800
Processing by PostsController#new as HTML
Redirected to http://www.example.com/
Filter chain halted as :authorize rendered or redirected
Completed 302 Found in 1ms (ActiveRecord: 0.0ms)
Started GET "/" for 127.0.0.1 at 2013-02-14 07:29:55 -0800
Processing by StaticsController#resume as HTML
  Rendered statics/_stars.html.erb (1.0ms)
  Rendered statics/_stars.html.erb (0.4ms)
  Rendered statics/_stars.html.erb (0.3ms)
  Rendered statics/_stars.html.erb (0.3ms)
  Rendered statics/_stars.html.erb (0.3ms)
  Rendered statics/_stars.html.erb (0.3ms)
  Rendered statics/_stars.html.erb (0.3ms)
  Rendered statics/_stars.html.erb (0.3ms)
  Rendered statics/_stars.html.erb (0.3ms)
  Rendered statics/_stars.html.erb (0.3ms)
  Rendered statics/_stars.html.erb (0.3ms)
  Rendered statics/_skills.html.erb (14.9ms)
  Rendered statics/_collapse_start.html.erb (0.6ms)
  Rendered statics/_collapse_start.html.erb (0.1ms)
  Rendered statics/_collapse_start.html.erb (0.1ms)
  Rendered statics/_collapse_start.html.erb (0.1ms)
  Rendered statics/_collapse_start.html.erb (0.1ms)
  Rendered statics/resume.html.erb within layouts/application (68.4ms)
  Rendered layouts/_shim.html.erb (0.2ms)
  Rendered layouts/_header.html.erb (1.0ms)
Completed 200 OK in 163ms (Views: 162.3ms | ActiveRecord: 0.0ms)
  [1m[35mUser Load (12.1ms)[0m  SELECT "users".* FROM "users" 
Started GET "/access" for 127.0.0.1 at 2013-02-14 07:29:55 -0800
Processing by SessionsController#new as HTML
  Rendered sessions/new.html.erb within layouts/application (1.2ms)
  Rendered layouts/_shim.html.erb (0.0ms)
  Rendered layouts/_header.html.erb (0.5ms)
Completed 200 OK in 32ms (Views: 32.1ms | ActiveRecord: 0.0ms)
  [1m[36m (0.1ms)[0m  [1mSAVEPOINT active_record_1[0m
  [1m[35mUser Exists (0.1ms)[0m  SELECT 1 AS one FROM "users" WHERE LOWER("users"."name") = LOWER('guest') LIMIT 1
Binary data inserted for `string` type on column `password_digest`
  [1m[36mSQL (30.0ms)[0m  [1mINSERT INTO "users" ("created_at", "name", "password_digest", "updated_at") VALUES (?, ?, ?, ?)[0m  [["created_at", Thu, 14 Feb 2013 15:29:55 UTC +00:00], ["name", "guest"], ["password_digest", "$2a$10$Y9NfnYjForrfufZOaqgQj.BdcHYLh.tkYomCVfHiJ4McbWMem445e"], ["updated_at", Thu, 14 Feb 2013 15:29:55 UTC +00:00]]
  [1m[35m (0.1ms)[0m  RELEASE SAVEPOINT active_record_1
Started POST "/sessions" for 127.0.0.1 at 2013-02-14 07:29:55 -0800
Processing by SessionsController#create as HTML
  Parameters: {"utf8"=>"✓", "name"=>"pword", "password"=>"[FILTERED]", "commit"=>"Log In"}
  [1m[36mUser Load (0.1ms)[0m  [1mSELECT "users".* FROM "users" WHERE "users"."name" = 'pword' LIMIT 1[0m
  Rendered sessions/new.html.erb within layouts/application (0.7ms)
  Rendered layouts/_shim.html.erb (0.0ms)
  Rendered layouts/_header.html.erb (0.5ms)
Completed 200 OK in 21ms (Views: 2.7ms | ActiveRecord: 0.1ms)
  [1m[35m (0.1ms)[0m  SELECT COUNT(*) FROM "users" 
  [1m[36m (0.5ms)[0m  [1mrollback transaction[0m

如您所见,从底部传递给会话控制器的第 6 行的“参数”包括名称“pword”(以及过滤后的可能为空的密码),这很奇怪/令人沮丧。

编辑 3——在我的测试组中使用最新版本的 Capybara。在这篇新帖子中,我在另一个控制器的规范中遇到了一个基本相同的问题。也就是说,我会告诉 Capybara 用“A”填充字段 1,用“B”填充 2,用“C”填充 3,来自该控制器的参数将显示 1 用“B”填充,2 用“C”填充" 和 3 空,好像 Capybara在我告诉它的字段之前填写每个字段。

编辑 4——按照 Dave S 的建议,我截取了登录过程的屏幕截图(以及发布过程的屏幕截图,如编辑 2 中所述,该过程具有相同的错误)。

两种不同的事情正在发生!在登录页面,看起来(因为密码被屏蔽了),实际上是在填写正确的信息(姓名==客人,密码==五颗星,与密码(和客人)的字符数相同),但是如果我保存页面而不是屏幕截图并单击,它会进入会话和错误,就像测试人员一样。

在我保存的页面/发布页面的屏幕截图中,Capybara 肯定填写了错误的字段。名称字段填写了我说的应该是内容,内容字段为空。我认为这是因为我为登录而不是为发布创建了新的唯一 ID,如果我为两者都这样做,我会看看会发生什么。我还会将密码更改为与“访客”不同的密码,然后再报告。

编辑 5——新的截图:

在此处输入图像描述

在此处输入图像描述

以及两个视图的代码,以了解这里可能有什么不同。(我还更改了上面的工厂代码,以使屏幕截图中的(正确)密码长度有意义。

# new posts _form.html.erb
<%= form_for(@post) do |f| %>
  <% if @post.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@post.errors.count, "error") %> prohibited this post from being saved:</h2>

      <ul>
      <% @post.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :name %><br />
    <%= f.text_field :name, id: "post_name" %>
  </div>
  <div class="field text-area">
    <%= f.label :content %><br />
    <%= f.text_area(:content, :size => '50x20', id: "post_content") %>
  </div>

    <div class="actions btn-group">
      <%= f.submit 'Post It', class: "btn" %>
    </div>

<% end %>

并登录:

# login (new.html.erb in sessions)

<div class="center_login">
    <h1>Log In</h1>
    <%= form_tag sessions_path do %>
      <div class="field">
        <%= label_tag :name %>
        <%= text_field_tag :name, params[:name], id: "sessions_name" %><br /> 
        # The above name change seemed to possibly fix it. The weird thing, though, is that
        # a similar change in the posts form above did NOT fix that problem.
      </div>
      <div class="field">
        <%= label_tag :password %>
        <%= password_field_tag :password %><br />
      </div><br>
      <div class="actions"><%= submit_tag "Log In", class: "btn" %></div>
    <% end %>
</div>

现在(在登录名中使用名为 seeions_name 的名称),登录工作 100%。参数是正确的,等等。但发布没有,因为(尽管我做了基本相同的更改)Capybara 仍然填写错误的字段。这是否使问题更清楚?我难住了。

编辑 6——完整的 repo 可以在这里找到

4

2 回答 2

0

我正好遇到了这个问题:使用 fill_in 时填写了错误的字段。

解决方案是遵循文档并使用字符串而不是匹配器的符号:

我替换了这个:

fill_in :email, with: email
fill_in :password, with: password

和:

fill_in "Email", with: email
fill_in "Password", with: password

然后它按预期工作

文档:https ://github.com/jnicklas/capybara#using-capybara-with-rspec

于 2013-07-05T07:43:49.073 回答
0

我在测试我的应用程序的登录功能时遇到了类似的问题:当我手动登录时它工作正常,但在使用 Capybara 测试它时登录失败。

您似乎遇到了一些我没有遇到的问题,即 Capybara 错误地填写字段。我不确定这是什么原因造成的,但您可能遇到的问题不止一个。调试后,我发现我的问题是由于一个错误的用户工厂。

我所拥有的是:

需要“摘要/sha1”

FactoryGirl.define do
  factory :user do
    login      'hitchcock'
    fname      'Alfred'
    lname      'Hitchcock'
    email      'alfred.hitchcock@example.com'
    password   Digest::SHA1.new << 'MacGuffin'
  end
end

设置密码的字段不正确。这是正确的版本:

    password   (Digest::SHA1.new << 'MacGuffin').to_s

User 类的“密码”字段实际上包含密码摘要,而不是密码,但我正在使用旧数据库。无论如何,我错误地计算了密码的摘要,忘记了to_s方法,这导致我的测试用例使用用户名“hitchcock”和密码“MacGuffin”的登录尝试失败。

现在,看看你的工厂,在我看来你可能有类似的问题。您的迁移文件20130206234907_create_users.rb如下所示:

class CreateUsers < ActiveRecord::Migration
  def change
    create_table :users do |t|
      t.string :name
      t.string :password_digest
      t.timestamps
    end
  end
end

这表明您正在存储密码的摘要,而不是密码本身,这是正确和正确的。但是,您的用户工厂在 filefactories.rb中是:

factory :user do
  name "guest"
  password "pwordtest"
  password_confirmation "pwordtest"
end

您的工厂没有password_digest为其创建的用户指定字段,因此在您posts_spec.rb创建用户时,您可以通过命令

user = FactoryGirl.create(:user)

我想知道是否在数据库中创建了一个用户,或者如果是,它的password_digest字段将是什么?请记住,在运行测试时,首先会清除测试数据库的内容,因此如果您的测试代码没有在数据库中创建有效用户,那么您的登录测试将无法进行。

于 2013-02-20T15:13:57.787 回答