在使用RSpec和Capybara进行工作时,我遇到了一个有趣的测试失败模式,通过对测试用例中的几行微妙的重新排列就可以解决...这些调整理论上不应该有所影响。
我正在开发自己的身份验证系统。 它目前可以正常工作,并且我可以使用浏览器登录/注销,会话也可以正常工作等等。 但是,尝试进行测试却失败了。 发生了一些我不太理解的事情,似乎与(看起来)无关的函数调用顺序有关。
require 'spec_helper'
describe "Sessions" do
it 'allows user to login' do
#line one
user = Factory(:user)
#For SO, this method hashes the input password and saves the record
user.password! '2468'
#line two
visit '/sessions/index'
fill_in 'Email', :with => user.email
fill_in 'Password', :with => '2468'
click_button 'Sign in'
page.should have_content('Logged in')
end
end
原测试失败了,登录失败了。在将'debugger'调用插入规范和控制器后,我发现问题所在:根据控制器的认识,用户未被插入到数据库中:
编辑添加ApplicationController。
class ApplicationController < ActionController::Base
helper :all
protect_from_forgery
helper_method :user_signed_in?, :guest_user?, :current_user
def user_signed_in?
!(session[:user_id].nil? || current_user.new_record?)
end
def guest_user?
current_user.new_record?
end
def current_user
@current_user ||= session[:user_id].nil? ? User.new : User.find(session[:user_id])
rescue ActiveRecord::RecordNotFound
@current_user = User.new
flash[:notice] = 'You\'ve been logged out.'
end
end
class SessionsController < ApplicationController
def login
user = User.where(:email=>params[:user][:email]).first
debugger ###
if !user.nil? && user.valid_password?(params[:user][:password])
#engage session
else
#run away
end
end
def logout
reset_session
redirect_to root_path, :notice => 'Logget Out.'
end
end
在控制台中,位于上述断点处:
1.9.2 vox@Alpha:~/Sites/website$ rspec spec/controllers/sessions_controller_spec.rb
/Users/vox/Sites/website/app/controllers/sessions_controller.rb:7
if !user.nil? && user.valid_password?(params[:user][:password])
(rdb:1) irb
ruby-1.9.2-p180 :001 > User.all.count
=> 0
ruby-1.9.2-p180 :002 >
然而,如果我在我的测试中重新排列几行代码,将“第二行”放在“第一行”的上面:
describe "Sessions" do
it 'allows user to login' do
#line two
visit '/sessions/index'
#line one
user = Factory(:user)
#For SO, this method hashes the input password and saves the record
user.password! '2468'
fill_in 'Email', :with => user.email
fill_in 'Password', :with => '2468'
click_button 'Sign in'
page.should have_content('Logged in')
end
end
在控制台中我得到了这个信息(与上面的断点相同):
1.9.2 vox@Alpha:~/Sites/website$ rspec spec/controllers/sessions_controller_spec.rb
/Users/vox/Sites/website/app/controllers/sessions_controller.rb:7
if !user.nil? && user.valid_password?(params[:user][:password])
(rdb:1) irb
ruby-1.9.2-p180 :001 > User.all.count
=> 1
为了简洁起见,我省略了用户对象内容的完整转储,但我可以保证测试按预期完成。
在这里交换行以使测试通过的行为与我的想法不太契合,并且已经在其他地方对我的测试造成了相当大的困扰。有什么提示吗?
我搜遍了谷歌和SO,寻找解决这个问题的思路,关于RSpec/Capybara和Sessions的SO问题很多,但似乎都不是很合适。
感谢您的关注。
更新:
我已经在测试中添加了断点(就在访问调用之前)和一些调试,得出了以下结论:(rdb:1) user
#<User id: 1, login_count: 1, email: "testuser1@website.com", encrypted_password: "11f40764d011926eccd5a102c532a2b469d8e71249f3c6e2f8b...", salt: "1313613794">
(rdb:1) User.all
[#<User id: 1, login_count: 1, email: "testuser1@website.com", encrypted_password: "11f40764d011926eccd5a102c532a2b469d8e71249f3c6e2f8b...", salt: "1313613794">]
(rdb:1) next
/Users/vox/Sites/website/spec/controllers/sessions_controller_spec.rb:19
fill_in 'Email', :with => user.email
(rdb:1) User.all
[]
所以显然在visit的过程中,某些事情告诉 Factory Girl 它已经完成了对用户对象的操作,因此它将其删除了?
编辑 经过仔细检查 test.log ,没有任何删除操作。 因此,我基本上回到了原点。