14 Stimmen

Factory Girl / Capybara löscht Datensätze mitten im Test aus der Datenbank?

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.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X