Factory Girl / Capybara borrando registros de la base de datos a mitad de la prueba?
Trabajando con RSpec y Capybara, obtengo un modo de falla de prueba interesante que desaparece con algunas reorganizaciones sutiles de líneas en el caso de prueba ... cosas que no deberían importar.
Estoy desarrollando mi propio sistema de autenticación. Actualmente funciona y puedo iniciar sesión / cerrar sesión con el navegador y la sesión funciona, etc. Sin embargo, intentar probar esto está fallando. Algo está sucediendo que no entiendo bien, lo que parece depender del orden de las llamadas (aparentemente) no relacionadas.
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
Como es, esa prueba falla ... falla el inicio de sesión. Después de insertar llamadas de 'depurador' tanto en la especificación como en el controlador, puedo ver por qué: el usuario no se está insertando en la base de datos en lo que respecta al controlador:
Edita agregando en 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
en la consola, en el punto de interrupción anterior:
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 >
Sin embargo, si reorganizo algunas líneas en mi prueba, colocando la línea 'dos' sobre la línea 'uno':
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
Obtengo esto en la consola (el mismo punto de interrupción que el anterior):
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
En aras de la brevedad, he omitido el volcado completo del contenido del objeto de usuario, pero puedo asegurarle que la prueba se completa como se esperaba.
Este comportamiento de intercambiar líneas para que la prueba pase realmente no encaja bien con mi idea de lo que debería estar sucediendo con estos comandos y ha demostrado ser muy útil para mis pruebas en otras áreas.
¿Alguna pista de lo que está pasando aquí?
He buscado en Google y SO ideas que presenten este problema, y no faltan las preguntas SO sobre RSpec / Capybara y Sessions. Sin embargo, nada parecía encajar del todo bien.
Gracias por mirar
Actualiza
He agregado un punto de interrupción (justo antes de una llamada de visita) y algo de depuración para la prueba y vuelvo con esto:
(rdb:1) user
#<User id: 1, login_count: 1, email: "[email protected]", encrypted_password: "11f40764d011926eccd5a102c532a2b469d8e71249f3c6e2f8b...", salt: "1313613794">
(rdb:1) User.all
[#<User id: 1, login_count: 1, email: "[email protected]", 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
[]
¿Entonces, claramente, algo en el camino que hace la visita es decirle a Factory Girl que se hizo con el objeto de usuario y, por lo tanto, lo elimina?
Edita Después de inspeccionar test.log cuidadosamente, nada está emitiendo ninguna eliminación. Así que estoy más o menos de vuelta al punto de partida.