奇怪的问题。
我正在尝试使用 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 可以在这里找到