Bei der Arbeit mit RSpec & Capybara erhalte ich einen interessanten Testfehlermodus, der mit ein paar subtilen Umstellungen von Zeilen im Testfall verschwindet...Dinge, die keine Rolle spielen sollten.
Ich entwickle gerade mein eigenes Authentifizierungssystem. Es funktioniert derzeit und ich kann mich mit dem Browser an- und abmelden und die Sitzung funktioniert usw. usw. Der Versuch, dies zu testen, schlägt jedoch fehl. Etwas ist los, dass ich nicht ganz verstehen, die scheint auf die Reihenfolge der (scheinbar) unverbundene Anrufe abhängen.
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
So wie es ist, schlägt dieser Test fehl...die Anmeldung schlägt fehl. Nach dem Einfügen von "Debugger"-Aufrufe in die Spezifikation und der Controller kann ich sehen, warum: der Benutzer ist nicht immer in die Datenbank eingefügt, soweit der Controller betroffen ist:
Editar Hinzufügen in 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
in der Konsole an dem oben genannten Haltepunkt:
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 >
Wenn ich jedoch einige Zeilen in meinem Test neu anordne, indem ich die Zeile "zwei" über die Zeile "eins" setze:
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
In der Konsole wird dies angezeigt (gleicher Haltepunkt wie oben):
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
Der Kürze halber habe ich den vollständigen Dump des Inhalts des Benutzerobjekts weggelassen, aber ich kann Ihnen versichern, dass der Test wie erwartet abläuft.
Dieses Verhalten des Vertauschens von Zeilen, um den Test zum Bestehen zu bringen, passt nicht wirklich gut zu meiner Vorstellung davon, was mit diesen Befehlen geschehen sollte, und hat sich als ziemliche Belastung für meine Tests in anderen Bereichen erwiesen.
Gibt es Hinweise, was hier vor sich geht?
Ich habe Google und SO nach Ideen durchforstet, die dieses Problem darstellen, und es gibt keinen Mangel an SO-Fragen zu RSpec/Capybara und Sessions. Nichts schien zu passen ganz richtig aber.
Vielen Dank für Ihren Besuch.
Update
Ich habe einen Haltepunkt (kurz vor einem Besuch aufrufen) und einige Debugging den Test hinzugefügt und kommen zurück mit diesem:
(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
[]
So eindeutig etwas auf dem Weg, dass Besuch tut ist sagen Factory Girl, dass seine fertig mit dem Benutzer-Objekt und so löscht sie es?
Editar Nachdem ich test.log sorgfältig inspiziert habe, wird nichts gelöscht. Ich stehe also mehr oder weniger wieder am Anfang.