2014-10-10 22 views
0

我對RoR比較陌生,經歷了Hart的教程並遇到了一些小問題。我希望你能幫助!Rails教程8.3認證測試未通過

我完成了第8章,並試圖讓最後一個測試通過,但我一直失敗。我是新來的所有這一切,所以任何幫助將不勝感激。我看了其他類似的問題,但並未真正找到我的解決方案。而且......我知道這只是一個測試,但我對這些事情是超級肛門的,我不會繼續前進,直到我知道100%我做錯了什麼。斷開連接在哪裏?我在這裏沒有看到什麼?

故障測試

No DRb server is running. Running in local process instead ... .........................................F......

Failures:

1) Authentication signin followed by signout Failure/Error: before { click_link "Sign out" } Capybara::ElementNotFound: Unable to find link "Sign out" # ./spec/requests/authentication_pages_spec.rb:34:in `block (4 levels) in '

Finished in 0.67649 seconds 48 examples, 1 failure

Failed examples:

rspec ./spec/requests/authentication_pages_spec.rb:35 # Authentication signin followed by signout

Randomized with seed 40273


Authentication_pages_spec.rb文件

require 'spec_helper' 

describe "Authentication" do 

    subject { page } 

    describe "signin" do 
    before { visit signin_path } 

    describe "with invalid information" do 
     before { click_button "Sign in" } 

     it { should have_title('Sign in') } 
     it { should have_selector('div.alert.alert-error') } 

     describe "after visiting another page" do 
     before { click_link "Home" } 
     it { should_not have_selector('div.alert.alert-error') } 
     end 
    end 

    describe "with valid information" do 
     let(:user) { FactoryGirl.create(:user) } 
     before { sign_in user } 

     it { should have_title(user.name) } 
     it { should have_link('Profile',  href: user_path(user)) } 
     it { should have_link('Settings', href: edit_user_path(user)) } 
     it { should have_link('Sign out', href: signout_path) } 
     it { should_not have_link('Sign in', href: signin_path) } 
    end 

    describe "followed by signout" do 
     before { click_link "Sign out" } 
     it { should have_link('Sign in') } 
    end 
    end 
end 
end 

sessions_controller.rb代碼

class SessionsController < ApplicationController 

    def new 
    end 

    def create 
    user = User.find_by(email: params[:session][:email].downcase) 
    if user && user.authenticate(params[:session][:password]) 
     sign_in user 
     redirect_to user 
    else 
     flash.now[:error] = 'Invalid email/password combination' 
     render 'new' 
    end 
    end 

    def destroy 
    sign_out 
    redirect_to root_url 
    end 
end 

sessions_helper.rb代碼

module SessionsHelper 

    def sign_in(user) 
    remember_token = User.new_remember_token 
    cookies.permanent[:remember_token] = remember_token 
    user.update_attribute(:remember_token, User.digest(remember_token)) 
    self.current_user = user 
    end 

    def signed_in? 
    !current_user.nil?  
    end 
    def current_user=(user) 
    @current_user = user 
    end 

    def current_user 
    remember_token = User.digest(cookies[:remember_token]) 
    @current_user ||= User.find_by(remember_token: remember_token) 
    end 

    def sign_out 
    current_user.update_attribute(:remember_token, User.digest(User.new_remember_token)) 
    cookies.delete(:remember_token) 
    self.current_user = nil 
    end 
end 

回答

0

你只在一個測試"with valid information"創建FactoryGirl新用戶。當你去下一次測試時,你沒有這個用戶,所以你需要在do end區塊"with valid information"中進行這個測試。

describe "Authentication" do 

    subject { page } 

    describe "signin" do 
    # You run it before all tests in this block 
    before { visit signin_path } 

    describe "with invalid information" do 
     # So, here you visit signin_path and click "Sign in" link 
     before { click_button "Sign in" } 

     it { should have_title('Sign in') } 
     it { should have_selector('div.alert.alert-error') } 

     describe "after visiting another page" do 
     before { click_link "Home" } 
     it { should_not have_selector('div.alert.alert-error') } 
     end 
    end 

    # Before this test you only visit signin_path 
    describe "with valid information" do 
     # After this you create new user with FactoryGirl... 
     let(:user) { FactoryGirl.create(:user) } 
     # ...and sign him in (before every test in this block) 
     before { sign_in user } 

     it { should have_title(user.name) } 
     it { should have_link('Profile',  href: user_path(user)) } 
     it { should have_link('Settings', href: edit_user_path(user)) } 
     it { should have_link('Sign out', href: signout_path) } 
     it { should_not have_link('Sign in', href: signin_path) } 
    end 

    # Here you again visit signin_path, but you don't have FactoryGirl user. 
    # You can have this user, if you move this block to previous: "with valid information" 
    describe "followed by signout" do 
     before { click_link "Sign out" } 
     it { should have_link('Sign in') } 
    end 
    end 
end 

因此,重構你的代碼是這樣的:

describe "with valid information" do 
    let(:user) { FactoryGirl.create(:user) } 
    before { sign_in user } 

    it { should have_title(user.name) } 
    it { should have_link('Profile',  href: user_path(user)) } 
    it { should have_link('Settings', href: edit_user_path(user)) } 
    it { should have_link('Sign out', href: signout_path) } 
    it { should_not have_link('Sign in', href: signin_path) } 

    describe "followed by signout" do 
    before { click_link "Sign out" } 
    it { should have_link('Sign in') } 
    end 
end 

這應該幫助。

完成RailsTutorial之後,我建議您閱讀"Everyday Rails: Testing with RSpec"should模式在測試中相當過時,並且使用expect -> to模式代替是一種很好的做法。

+0

太棒了!這完全有意義,它的工作!非常感謝你的幫助和評論,這些評論確實幫助我瞭解正在發生的事情的過程。我希望Rails指南有這個。我也會檢查一下這本書! – Igor 2014-10-10 23:10:17