2010-08-12 39 views
0

我正在研究Rails應用程序,它要求您登錄才能看到任何東西。對於單元測試,這不是一個問題,因爲它們直接與模型交互。對於集成測試,這不是一個大問題,因爲我可以通過Rails的post方法讓適當的用戶登錄。將所有對權限敏感的測試都放入集成測試中似乎有意義(例如,測試用戶不能編輯其他人的評論)。如何測試權限管理的Rails應用程序?

但是,我在處理功能測試時遇到了問題。對我來說,測試功能並不關係用戶權限,這對我來說似乎是有道理的。現在,我找不到一個好的方法來做到這一點,因爲所有請求都會將測試客戶端彈回到登錄頁面。

我試過的一個不雅的解決方案是在setup方法中放入這個日誌請求,但是Rails測試者試圖訪問一個動作而不是一個路徑。特別是,我有

def setup 
    post /sessions/create, {:username => 'testdbadmin', :password => 'password} 
end 

但根據日誌,它只是試圖訪問SomeController#/會議/創建,這顯然不是意圖。

我覺得我錯過了一些很大的內置方式來做到這一點。請指教。

回答

4

我在我的功能測試中通過在我的設置中設置有效的登錄會話數據來有效地模擬用戶已經通過身份驗證(或沒有,視情況而定)的請求。

我在test_helper.rb中一個輔助方法:

def login(typ = :user, options = {}) 
    user = Factory.create(typ, {:username => "Joe"}.merge(options)) 
    session["user_id"] = user.id.to_s 
    end 

然後在我的功能測試:

class AccountsControllerTest < ActionController::TestCase 
    context "Fresh session" do 
    setup do 
     @user = Factory.create(:user) 
    end 

    should "be redirected to the login page if not logged in" do 
     get :show 
     assert_redirected_to login_path 
    end 

    context "Logged in user with profile" do 
    setup do 
     @user = login 
    end 

    should "get the account home page" do 
     get :show 
     assert_response :success 
    end 
    end 
end 
1

而不是測試在功能測試這一切,我會用功能測試和黃瓜功能相結合。您需要測試用戶登錄時是否可以訪問應用程序的各個部分。這是黃瓜功能。然後你想要測試當用戶沒有登錄時,他們不能訪問這些部分。這是功能測試。

我會寫的黃瓜功能是這樣的:

Feature: Viewing accounts 
    In order to update my account information 
    As a user 
    I want to access my profile page 

    Background: 
    Given a user exists: 
     | login | password  | 
     | Radar | superpassword | 
    And I am logged in as them 

    Scenario: My profile page 
    When I follow "Account" 
    Then I should see "Profile Information" 

我假設一對夫婦的事情在這裏。首先您的用戶使用登錄名和密碼登錄。您可能會將此作爲電子郵件和密碼,但我相信您瞭解這一要點。

「我以他們身份登錄」步驟實際上沒有設置會話,而是實際上經歷了登錄用戶的過程。我會寫這兩個後臺步驟像這樣*:

Given /^a user exists:$/ do |table| 
    table.hashes.each do |user| 
    @user = User.create!(user) 
    end 
end 


Given /^I am logged in as them$/ do 
    steps(%Q{ 
    Given I am on the homepage 
    And I follow "Login" 
    And I fill in "Login" with "#{@user.login}" 
    And I fill in "Password" with "#{@user.password}" 
    And I press "Login" 
    Then I should see "Login successful." 
    }) 
end 

通過這些步驟定義,然後該方案將運行。我在這裏假設你在頁面上的某個地方登錄操作重定向到「帳戶」。當這個鏈接被點擊時,我也假設它進入了一個頁面,上面寫着「Profile Information」。

*這是一個稍微做作的例子。 「用戶存在」步驟可以佔用多行。


現在進行功能測試。我是一個RSpec類型的人,所以我會這樣寫。

require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') 

describe AccountsController do 

    context "not logged in users" do 
    it "cannot access the profile action" do 
     get :profile 
     flash[:alert].should eql("You must be logged in to access that action.") 
     response.should redirect_to(login_path) 
    end 
    end 
end 

檢查用戶是否登錄的before_filter將通過此功能測試進行測試。因爲它是一個private方法(這是一個private方法,對吧?)不應該直接測試它。在這裏我再次提出一些假設,當這個before_filter「失敗」時,它將flash[:alert]設置爲一些特定的消息並且重定向到login_path


在總結

所以:測試所有的東西,用戶可以通過點擊左右,並在使用黃瓜在網站上填寫表格做的,但事情比如去保護的操作或丟失的資源使用功能測試/控制器規範。

+0

感謝您的詳盡答案和示例。我已經熟悉了Cucumber的要點,儘管時間有限,所以我不能將它應用到這個直接的項目中,我將來肯定會給出這種抽象的BDD。我看到評估背後的原因,我不應該在功能測試中測試權限管理功能,而應該將其放在集成/黃瓜測試中。 – 2010-08-13 13:50:24

相關問題