2011-10-30 7 views
9

Ho appena terminato chapter 10 of the Ruby on Rails Tutorial, aggiungendo la possibilità di modificare/aggiornare, indicizzare e distruggere gli utenti. Sembra che tutto funzioni correttamente nella mia app, ma molti dei miei test non funzionano quando eseguo RSpec.Perché i test di RSpec non funzionano, ma la mia app funziona?

Ho impostato user_controller_spec esattamente come lo fa il libro e anche il mio codice applicazione è lo stesso. Un problema potrebbe essere che sto usando Rails 3.1.1 rispetto a Rails 3.0 che usa nel libro? Non è stato davvero un problema per i test precedenti, solo occasionalmente per alcune linee di codice diverse. I problemi hanno iniziato a comparire dopo l'avvio di section 10.2.1.

Ecco l'elenco degli errori che sto vedendo e per favore fatemi sapere se avete bisogno di maggiori informazioni. Grazie!

1) UsersController GET 'index' for signed-in users should be successful 
Failure/Error: response.should be_success 
    expected success? to return true, got false 
# ./spec/controllers/users_controller_spec.rb:31:in `block (4 levels) in <top (required)>' 

2) UsersController GET 'index' for signed-in users should have the right title 
Failure/Error: response.should have_selector("title", :content => "All users") 
    expected following output to contain a <title>All users</title> tag: 
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> 
    <html><body>You are being <a href="http://test.host/signin">redirected</a>.</body></html> 
# ./spec/controllers/users_controller_spec.rb:36:in `block (4 levels) in <top (required)>' 

3) UsersController GET 'index' for signed-in users should have an element for each user 
Failure/Error: response.should have_selector("li", :content => user.name) 
    expected following output to contain a <li>Richard Berger</li> tag: 
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> 
    <html><body>You are being <a href="http://test.host/signin">redirected</a>.</body></html> 
# ./spec/controllers/users_controller_spec.rb:42:in `block (5 levels) in <top (required)>' 
# ./spec/controllers/users_controller_spec.rb:41:in `each' 
# ./spec/controllers/users_controller_spec.rb:41:in `block (4 levels) in <top (required)>' 

4) UsersController GET 'index' for signed-in users should paginate users 
Failure/Error: response.should have_selector("div.pagination") 
    expected following output to contain a <div.pagination/> tag: 
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> 
    <html><body>You are being <a href="http://test.host/signin">redirected</a>.</body></html> 
# ./spec/controllers/users_controller_spec.rb:48:in `block (4 levels) in <top (required)>' 

5) UsersController GET 'edit' should be successful 
Failure/Error: response.should be_success 
    expected success? to return true, got false 
# ./spec/controllers/users_controller_spec.rb:184:in `block (3 levels) in <top (required)>' 

6) UsersController GET 'edit' should have the right title 
Failure/Error: response.should have_selector("title", :content => "Edit user") 
    expected following output to contain a <title>Edit user</title> tag: 
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> 
    <html><body>You are being <a href="http://test.host/signin">redirected</a>.</body></html> 
# ./spec/controllers/users_controller_spec.rb:189:in `block (3 levels) in <top (required)>' 

7) UsersController GET 'edit' should have a link to change the Gravatar 
Failure/Error: response.should have_selector("a", :href => gravatar_url, :content => "change") 
    expected following output to contain a <a href='http://gravatar.com/emails'>change</a> tag: 
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> 
    <html><body>You are being <a href="http://test.host/signin">redirected</a>.</body></html> 
# ./spec/controllers/users_controller_spec.rb:195:in `block (3 levels) in <top (required)>' 

8) UsersController PUT 'update' failure should render the 'edit' page 
Failure/Error: response.should render_template('edit') 
    expecting <"edit"> but rendering with <""> 
# ./spec/controllers/users_controller_spec.rb:214:in `block (4 levels) in <top (required)>' 

9) UsersController PUT 'update' failure should have the right title 
Failure/Error: response.should have_selector("title", :content => "Edit user") 
    expected following output to contain a <title>Edit user</title> tag: 
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> 
    <html><body>You are being <a href="http://test.host/signin">redirected</a>.</body></html> 
# ./spec/controllers/users_controller_spec.rb:219:in `block (4 levels) in <top (required)>' 

10) UsersController PUT 'update' success should change the user's attributes 
Failure/Error: @user.name.should == @attr[:name] 
    expected: "New Name" 
     got: "Richard Berger" (using ==) 
# ./spec/controllers/users_controller_spec.rb:232:in `block (4 levels) in <top (required)>' 

11) UsersController PUT 'update' success should redirect to the user show page 
Failure/Error: response.should redirect_to(user_path(@user)) 
    Expected response to be a redirect to <http://test.host/users/1> but was a redirect to <http://test.host/signin> 
# ./spec/controllers/users_controller_spec.rb:238:in `block (4 levels) in <top (required)>' 

12) UsersController PUT 'update' success should have a flash message 
Failure/Error: flash[:success].should =~ /updated/ 
    expected: /updated/ 
     got: nil (using =~) 
# ./spec/controllers/users_controller_spec.rb:243:in `block (4 levels) in <top (required)>' 

13) UsersController authentication of edit/update pages for signed-in users should require matching users for 'edit' 
Failure/Error: response.should redirect_to(root_path) 
    Expected response to be a redirect to <http://test.host/> but was a redirect to <http://test.host/signin> 
# ./spec/controllers/users_controller_spec.rb:276:in `block (4 levels) in <top (required)>' 

14) UsersController authentication of edit/update pages for signed-in users should require matching users for 'update' 
Failure/Error: response.should redirect_to(root_path) 
    Expected response to be a redirect to <http://test.host/> but was a redirect to <http://test.host/signin> 
# ./spec/controllers/users_controller_spec.rb:281:in `block (4 levels) in <top (required)>' 

15) UsersController DELETE 'destroy' as a non-admin user should protect the page 
Failure/Error: response.should redirect_to(root_path) 
    Expected response to be a redirect to <http://test.host/> but was a redirect to <http://test.host/signin> 
# ./spec/controllers/users_controller_spec.rb:303:in `block (4 levels) in <top (required)>' 

16) UsersController DELETE 'destroy' as an admin user should destroy the user 
Failure/Error: lambda do 
    count should have been changed by -1, but was changed by 0 
# ./spec/controllers/users_controller_spec.rb:315:in `block (4 levels) in <top (required)>' 

17) UsersController DELETE 'destroy' as an admin user should redirect to the users page 
Failure/Error: response.should redirect_to(users_path) 
    Expected response to be a redirect to <http://test.host/users> but was a redirect to <http://test.host/signin> 
# ./spec/controllers/users_controller_spec.rb:322:in `block (4 levels) in <top (required)>' 

UPDATE:

ho risolto 2 degli errori, ma la maggior parte sono ancora persiste. Un problema sembra essere che quando il test sta cercando di "ottenere: indice", non sta trovando la pagina corretta a causa di un reindirizzamento (alla pagina di/sign). Non ho istituito alcun reindirizzamento (di proposito, comunque), ma forse qualcuno ha un'idea di come questo potrebbe essere successo e come potrebbe essere risolto?

UPDATE # 2:

Per @ di bkempner richiesta, ecco il codice pertinente dal users_controller_spec e l'users_controller (users_controller_spec prima). Sacco di codice, ma molti errori ...:

describe "for signed-in users" do 

    before(:each) do 
    @user = test_sign_in(Factory(:user)) 
    second = Factory(:user, :email => "[email protected]") 
    third = Factory(:user, :email => "[email protected]") 

    @users = [@user, second, third] 
    30.times do 
     @users << Factory(:user, :email => Factory.next(:email)) 
    end 
    end 

    it "should be successful" do 
    get :index 
    response.should be_success 
    end 

    it "should have the right title" do 
    get :index 
    response.should have_selector("title", :content => "All users") 
    end 

    it "should have an element for each user" do 
    get :index 
    @users[0..2].each do |user| 
     response.should have_selector("li", :content => user.name) 
    end 
    end 

    it "should paginate users" do 
    get :index 
    response.should have_selector("div.pagination") 
    response.should have_selector("span.diabled", :content => "Previous") 
    response.should have_selector("a", :href => "/users?page=2", :content => "2") 
    response.should have_selector("a", :href => "/users?page=2", :content => "Next") 
    end 
end 

describe "GET 'edit'" do 

    before(:each) do 
    @user = Factory(:user) 
    test_sign_in(@user) 
    end 

    it "should be successful" do 
    get :edit, :id => @user 
    response.should be_success 
    end 

    it "should have the right title" do 
    get :edit, :id => @user 
    response.should have_selector("title", :content => "Edit user") 
    end 

    it "should have a link to change the Gravatar" do 
    get :edit, :id => @user 
    gravatar_url = "http://gravatar.com/emails" 
    response.should have_selector("a", :href => gravatar_url, :content => "change") 
    end 
end 

describe "PUT 'update'" do 

    before(:each) do 
    @user = Factory(:user) 
    test_sign_in(@user) 
    end 

    describe "failure" do 

    before(:each) do 
     @attr = { :email => "", :name => "", :password => "", :password_confirmation => "" } 
    end 

    it "should render the 'edit' page" do 
     put :update, :id => @user, :user => @attr 
     response.should render_template('edit') 
    end 

    it "should have the right title" do 
     put :update, :id => @user, :user => @attr 
     response.should have_selector("title", :content => "Edit user") 
    end 
    end 

    describe "success" do 

    before(:each) do 
     @attr = { :name => "New Name", :email => "[email protected]", :password => "barbaz", :password_confirmation => "barbaz" } 
    end 

    it "should change the user's attributes" do 
     put :update, :id => @user, :user => @attr 
     @user.reload 
     @user.name.should == @attr[:name] 
     @user.email.should == @attr[:email] 
    end 

    it "should redirect to the user show page" do 
     put :update, :id => @user, :user => @attr 
     response.should redirect_to(user_path(@user)) 
    end 

    it "should have a flash message" do 
     put :update, :id => @user, :user => @attr 
     flash[:success].should =~ /updated/ 
    end 
    end 
end 

describe "authentication of edit/update pages" do 

    describe "for signed-in users" do 

    before(:each) do 
     wrong_user = Factory(:user, :email => "[email protected]") 
     test_sign_in(wrong_user) 
    end 

    it "should require matching users for 'edit'" do 
     get :edit, :id => @user 
     response.should redirect_to(root_path) 
    end 

    it "should require matching users for 'update'" do 
     get :update, :id => @user, :user => {} 
     response.should redirect_to(root_path) 
    end 
    end 
end 

describe "DELETE 'destroy'" do 

    before(:each) do 
    @user = Factory(:user) 
    end 

    describe "as a non-admin user" do 
    it "should protect the page" do 
     test_sign_in(@user) 
     delete :destroy, :id => @user 
     response.should redirect_to(root_path) 
    end 
    end 

    describe "as an admin user" do 

    before(:each) do 
     admin = Factory(:user, :email => "[email protected]", :admin => true) 
     test_sign_in(admin) 
    end 

    it "should destroy the user" do 
     lambda do 
     delete :destroy, :id => @user 
     end.should change(User, :count).by(-1) 
    end 

    it "should redirect to the users page" do 
     delete :destroy, :id => @user 
     response.should redirect_to(users_path) 
    end 
    end 
end 

E ora l'intero users_controller:

class UsersController < ApplicationController 
before_filter :authenticate, :only => [:index, :edit, :update, :destroy] 
before_filter :correct_user, :only => [:edit, :update] 
before_filter :admin_user, :only => :destroy 

def index 
    @title = "All users" 
    @users = User.paginate(:page => params[:page]) 
end 

def show 
    @user = User.find(params[:id]) 
    @title = @user.name 
end 

def new 
    @user = User.new 
    @title = "Sign up" 
end 

def create 
    @user = User.new(params[:user]) 
    if @user.save 
    sign_in @user 
    flash[:success] = "Welcome to the Sample App!" 
    redirect_to @user 
    else 
    @title = "Sign up" 
    render 'new' 
    end 
end 

def edit 
    @title = "Edit user" 
end 

def update 
    @user = User.find(params[:id]) 
    if @user.update_attributes(params[:user]) 
    flash[:success] = "Profile updated" 
    redirect_to @user 
    else 
    @title = "Edit user" 
    render 'edit' 
    end 
end 

def destroy 
    User.find(params[:id]).destroy 
    flash[:success] = "User destroyed." 
    redirect_to users_path 
end 

private 

    def authenticate 
    deny_access unless signed_in? 
    end 

    def correct_user 
    @user = User.find(params[:id]) 
    redirect_to(root_path) unless current_user?(@user) 
    end 

    def admin_user 
    redirect_to(root_path) unless current_user.admin? 
    end 
end 
+0

fatto a capire questo? hai lat modificato 20 giorni fa e ho appena iniziato il porting su 3.1 e avendo lo stesso problema. –

risposta

1

Ho avuto lo stesso problema e trovato la risposta postato here.

in pratica RSPEC ha bisogno sia di @current_user che di utente corrente per essere impostato per sign_in e sign_out. Strano e fastidioso, ma forse la ragione per cui si potrebbe considerare l'utilizzo di Devise in un'app di produzione!

+0

quindi sembra che abbia risolto il mio problema, anche se non sono ancora del tutto sicuro del perché. grazie per l'aiuto! – RBergs

0

Fornendo il controller e il codice di prova sarebbe utile. Ma senza di loro la mia ipotesi è che vi manca questo nel blocco prima per i test in mancanza:

@user = Factory(:user) 
test_sign_in(@user) 

Il reindirizzamento sta accadendo a causa di tutto ciò che la logica di autorizzazione viene utilizzato nel tutorial, penso che sia dettagliato 10.11 e 10.12.

Questo è un trucchetto comune che vedo nei test del controller con auth, speriamo che sia tutto ciò che è anche per te.

EDIT:

Grazie per fornire il proprio codice.

Ecco un paio di cose che ho notato:

1.) avarie 1-14, 19 sono dovuti alla autenticazione utente non funziona, in particolare signed_in ?. I test del controller di sessione stanno passando? È necessario accertarsi che tali passaggi vengano eseguiti prima di testare il controller degli utenti poiché dipende da tale funzionalità.

2.) avarie 15-18 sono perché probabilmente non hai creato la migrazione per aggiungere l'attributo booleano nel Listato 10.35 oppure è necessario eseguire la migrazione sul database di test: rake db:test:prepare

Mi dispiace non è stato in grado di individuare tutti i tuoi problemi, ma spero che ti faccia un passo nella giusta direzione.

+0

Grazie per la risposta, ma sfortunatamente non penso che sia questo il problema. Devo aggiungere il mio controller e il codice di test al post principale ora per ricontrollare. – RBergs

+0

hmm, grazie per esserti attenuto al problema. tutti i miei test del controller di sessione stanno passando, quindi non pensare che sia il problema. anche abbastanza sicuro ho migrato l'attributo e il database. appena aggiornato l'elenco degli errori anche perché ci sono stati un paio di modifiche minori. ancora non so cosa c'è che non va, purtroppo! – RBergs

0

Verificare che deny_access in SessionsHelper sia definito prima del blocco private.

Il libro è un errore di battitura che implica che si dovrebbe mettere deny_access alla fine del modulo. Sfortunatamente questo significa che la funzione è definita come privata.

module SessionsHelper 
    . 
    . 
    . 
    def deny_access 
    redirect_to signin_path, :notice => "Please sign in to access this page." 
    end 
end 

Il codice corretto sul sito Railstutorial.org è inferiore:

module SessionsHelper 
    . 
    . 
    . 
    def deny_access 
    redirect_to signin_path, :notice => "Please sign in to access this page." 
    end 

    private 
    . 
    . 
    . 
end 
+0

grazie per il suggerimento, ma ho già ottenuto deny_access nel posto giusto. – RBergs

0

Ho avuto lo stesso problema e utilizzando Rails 3.1.3. Questa è la mia soluzione.

In primo luogo, assicurarsi che entrambi:

def current_user=(user) 
    @current_user = user 
end 

def current_user 
    @current_user ||= user_from_remember_token 
end 

sono in sessions_helper.rb

Inoltre, nel cambiamento sessions_helper.rb:

def sign_out 
    cookies.delete(:remember_token) 
    current_user.nil 
end 

a

def sign_out 
    cookies.delete(:remember_token) 
    self.current_user.nil 
end 

One più cosa

In cambio spec_helper.rb:

def test_sign_in(user) 
    controller.sign_in(user) 
end 

a

def test_sign_in(user) 
    controller.current_user = user 
end 

vedere se questo aiuta, non ho completato il capitolo, ma questo mi passa attraverso 10.2.1. Qualcuno con più esperienza può commentare perché questo funziona. Ho letto un'altra soluzione che ha scritto attorno a before_filter per far passare rspec.

0

Hai una chiamata render_views dopo il livello superiore describe in users_controller_spec?

+0

sì, grazie per il suggerimento – RBergs

0

mi sono imbattuto in questo stesso problema oggi usando le rotaie 3.1.3. Tuttavia, sono andato al sito GitHub per il campione app railstutorial e notato la sessions_helper.erb ci aveva alcuni cambiamenti.

1.) Aggiungere il 'sé' parola chiave per 'current_user' nel metodo sign_in (utente):

def sign_in(user) 
    cookies.permanent.signed[:remember_token] = [user.id, user.salt] 
    self.current_user = user 
end 

2.) Questo vale anche per il metodo 'sign_out', aggiungere l' 'auto 'parola chiave per 'current_user'

def sign_out 
    cookies.delete(:remember_token) 
    self.current_user = nil 
end 

ho fatto altre modifiche e tutti i test passano.

+0

interessante, quindi non sono sicuro del perché, ma l'aggiunta di auto NON funziona, mentre si aggiunge una seconda linea che si riferisce a @current_user (come [di riferimento] (http://stackoverflow.com/questions/6821692/cookies-do-not-persist-in-rspec-on-rails-3-1)) ha funzionato ... – RBergs

Problemi correlati