想有一下RSPec來作BDD開發,地發現中文資料太少了,無耐只能本身去主頁上看資料,作爲愛國者,俺的英文真爛得不成,不過翻完了,發出來你們樂一樂吧。shell
Spec::rails
---------------------------
一個將RSpec引入Rails的Rails插件
特色:
1. 可使用RSpec獨立的測試models,views,controllers和heplers
2. 整合了具夾(fixture)的載入
3. 爲models和controllers特別製做的生成器,能夠生成指定的測試RSpec文件來代替原來rails默認生成的tests文件。
4. 增長了不少易讀的匹配器
願景:
對那些剛認識TDD這個概念的人來講,rails的測試支持是一個大的飛躍。弄好這些測試就至關的棒了,由於這樣的rails程序一般會比沒有測試支持的rails程序要容易維護的多。
對於咱們這些經歷了TDD到如今的BDD的人來講,還必須考慮在現有支持上那些spec之間依賴性的問題。爲此,RSpec支持4種規範。這主要啓發於Test::Rails,這個zenTest內置rails框架。
咱們還創建良好的mocking和stubbing的支持,以助於打破那些不一樣關聯間的依賴關係。數據庫
不一樣類型的Example Groups:
-------------------------------------------
對以下示例的spec類型,Spec::Rails有各自不一樣的ExampleGroups子類來支持:ruby
Model Examples
這個和rails內置的單元測試工具相同。諷剌的是(對那些傳統的TDD'er),咱們認爲這些只是與數據庫相關的(言下之意,rails內置的test只是提供了數據庫相關的測試)。
詳細示例session
Controller Examples
除了不能真的給你轉向views外,這和你在rails裏作功能測試差很少。並且若是你喜歡,你也能夠強制它轉向一個view。你能夠設置預期的模板,以代替設置預期轉向的頁面。
詳細示例app
view Examples
這是rails功能測試的別一部分。View spec可讓你創建設置指定(感謝ZenTest)
詳細示例框架
Helper示例
你能夠直接測試你heplers裏的指定方法。
詳細示例dom
Fixtures
--------------------------------
你能夠在你任何的specs中使用fixture,如model,view,controller或helper,均可以。若是你想在全局中使用fixture,你能夠在spec/spec_helper.rb設置。看下面的例子:ide
命名約定:
爲了明確和一致,RSpec在目錄和rake任務上使用和Rails內置測試模塊稍微不一樣的命名約定
project
|
+--app
|
+--...
|
+--spec
|
+-- spec_helper.rb
|
+-- controllers
|
+-- helpers
|
+-- models
|
+-- views
Rake任務也對應的命名函數
Models
---------------------
Model的spec在SRAILS_ROOT/spec/models/目錄中,並提供對fixtures的支持工具
Expectations
---------------------
Model樣板支持以下的自定義Expectations
詳見:Spec::Rails::Expectations
Records
Model.should have(:no).records
Model.should have(1).record
Model.should have(3).records
這個比Model.find(:all).length.should == 3.要簡略一些
Error
model.should have(:no).errors_on(:attribute)
model.should have(1).error_on(:attribute)
model.should have(3).errors_on(:attribute)
Controllers
-----------------------------
Controllers的spec在$RAILS_ROOT/spec/controllers/下
相對Test::Unit,Spec::Rails不須要在setup方法中初始化controller。取而代之的是把controller類傳給describe方法。Spec::Rails會自動給你實例化一個controller,在Examples中你能夠直接訪問該controller的方法
與views獨立開來
-----------------------------
默認狀況下,Spec::Rails將你的Controller actions與相關的views獨立開來。這就讓你能夠在尚未views的時候測試你的controllers,並在當views出錯的時候保持這些(controller的)spec結果。
整合views
------------------------------
若是你要整合views的測試功能(在不少的功能測試中),你能夠在代碼中加入「integrate_views」
describe ArticlesController do
integrate_views
...
end
整合後,你可使用views中使用才能使用的Expectations。詳見views Examples
與數據庫分離
-----------------------------
咱們強烈建議您使用RSpec的mocking/stubbing框架來攔截類級的調用,如:find、:create甚至:new,從而引入mock實例來代替事實的active_record實例 。
這允許你的specs專一於controller所處理的事而不用擔憂那些複雜的驗證和關聯,這些驗證和關聯spec
會在Model Examples中去處理。
account = mock_model(Account)
Account.should_receive(:find).with("37").and_return(account)
或
account = mock_model(Account)
Account.stub!(:find).and_return(account)
Mocks和Stubs框架詳細信息詳見其文檔。
Response Expectations
----------------------------
這個Expectations在分離模式或整合模式中都能使用。詳見Spec::Rails::Expectations。
Response.should be_success
當返回200狀態,測試才能經過。注:分離模式下,這也返回真,因此它的用處不大,但起碼你的specs不會終止。
response.should be_success
response.should be_redirect
返回300-399狀態時經過。
response.should be_redirect
response.should render_template
get 'some_action'
response.should render_template("path/to/template/for/action")
response.should have_text
get 'some_action'
response.should have_text("expected text")
response.should redirect_to
get 'some_action'
response.should redirect_to(:action => 'other_action')
還支持以下的格式:
response.should redirect_to(:action => 'other_action')
response.should redirect_to('path/to/local/redirect')
response.should redirect_to('http://test.host/some_controller/some_action')
response.should redirect_to('http://some.other.domain.com')
assigns, flash and session
使用以下方法訪問 assigns, flash 和session.
assigns[:key]
flash[:key]
session[:key]
Routing Expectations(路由Expectations)
--------------------------------
驗證經過路由來得到的地址
route_for(:controller => "hello", :action => "world").should == "/hello/world"
驗證路由發送過來的參數
params_from(:get, "/hello/world").should == {:controller => "hello", :action => "world"}
Views
-----------------------------
View Examples位於$RAILS_ROOT/spec/views/。
Spec::Rails支持徹底從他們controllers分離出的views測試。
這讓你能夠在沒有controllers或是相關acitons被開發以前的時候測試和寫你的views。這也意味着controllers中引入的bugs並不會使views的測試用例失敗。
正如介紹中說有,這是一個很大的好處,可是他們將controllers和他們的views關互產生的Bugs給隱藏起來了。咱們強烈建議將這些獨立的views測試與高層次的集成測試結合起來,最好使用Cucumber。
注:Cucumber是一個BDD(BehaviourDrivenDevelopment)工具。
Spec::Rails::Expectations中還提供了幾個可用的函數。
Conveniences
-------------------------------
assigns
使用assigns[:key]來給view中的實例變量賦值。咱們推薦您這裏使用mock框架,而不是使用真實的model對象,這樣可使view的spec從models的變動中獨立開來。
# example
article = mock_model(Article)
article.should_receive(:author).and_return("Joe")
article.should_receive(:text).and_return("this is the text of the article")
assigns[:article] = article
assigns[:articles] = [article]
# template
<% for article in @articles -%>
<!-- etc -->
flash,params和session
使用flash[:key],params[:key] 和session[:key]來給view example中的值賦值。
# example
flash[:notice] = "Message in flash"
params[:account_id] = "1234"
session[:user_id] = "5678"
# template
<%= flash[:notice] %>
<%= params[:account_id] %>
<%= session[:user_id] %>
Examples支持下面的自定義expectations
----------------------
Spec::Rails的view Examples支持下面的自定義expectations
response.shoud have_tag
這個覆蓋了assert_select,並能夠在集成模式下的全部view examples和controller Examples均可以使用。
response.should have_tag('div') #若是有div標記則經過
response.should have_tag('div#interesting_div')
response.should have_tag('div', 'expected content')
response.should have_tag('div', /regexp matching expected content/)
response.should have_tag('form[action=?]', things_path)
response.should have_tag("input[type=?][checked=?]", 'checkbox', 'checked')
response.should have_tag('ul') do
with_tag('li', 'list item 1')
with_tag('li', 'list item 2')
with_tag('li', 'list item 3')
end
注:任何的hash值均可以是Strings或regexps,並獲得相應的評價。
response[:capture].should have_tag
這個方法能夠訪問那些被content_for捕獲的內容。
1.example
response[:sidebar].should have_tag(‘div’)
2.template
<% content_for :sidebar do %>
Sidebar content here
<% end %>
Mocking與stubbing helpers
若是你但願使用mock或stub的helper方法,這些能夠在template對象中完成:
template.should_receive(:current_user).and_return(mock("user"))
Helpers
----------------------------------------
Helper Examples在$RAILS_ROOT/spec/helpers/中
寫helpers的specs很容易,只要告訴ExampleGrouphelper的名字就能夠了
describe RegistrationHelper do
...
end
這將會在ExampleGroup中獲得一個包含了這個helper的對象
Conveniences
---------------------
assigns
使用assigns[:key]來在包含了這個helper的view中給實例變量賦值。詳見上面的鴿子。
writing
---------------------------
使用Spec::Rails寫Examples介紹
Spec::Rails支持4種不一樣類型的可招執examples
1.Models Examples
2.View Examples
3.Controllor Examples
4.Helper Examples
使用這些各專門ExampleGroup子類可讓你訪問適當的服務和方法。他們被放在各自相應的目錄中,並以*_spec.rb的明顯方法標註出來:
spec/controllers/**/*_spec.rb
spec/helpers/**/*_spec.rb
spec/models/**/*_spec.rb
spec/views/**/*_spec.rb
警告:若是你沒有遵照這些約定,那能夠得不到正確的ExampleGroup子類。若是你更喜歡無論這些約定,那你也能夠經過傳遞一個hash值給describe方法來得到正確的ExampleGroup子類:
describe "some model", :type => :model do
...
end
在:model,:view,:controller和:helper都生效。
Generators(生成器)
---------------------------------
Spec::Rails包含了一個生成器,你能夠用來生成models和RESTfulControllers,它和Rails內置的生成器基本同樣。 惟一不一樣的是,他多幫你會在spec目錄下生成一個specs來代替test,還有一個fixtures用來提供測試數據。以下例:
ruby script/generate rspec_scaffold purchase order_id:integer created_at:datetime amount:decimal
ruby script/generate rspec_model person
ruby script/generate rspec_controller person
詳細的用法,能夠以上命令不加參數得到其幫助 。
運行
---------------------
標準的spec命令:
script/spec path/to/directory/with/specs
script/spec path/to/individual_spec.rb
快速運行模式--drb(推薦)
------------------------
每次運行 都輸入全部的Rails環境變量,spec運行起來就很慢了。爲了加速測試速度,Spec::Rails安裝一個守護進程腳本,用於加載本地Rails應用,並用DRb偵聽傳入的鏈接。
打開一個shell來運行spec服務:
script/spec_server
如今你可使用--drb參數來使用這個功能了。
若是你使用Rake來運行,應該把--drb加給spec/spec.opts文件。
注意到默認狀況下,有的類和modules不要rails從新載入,在spec中也是同樣的。你也能夠修改rails的環境文件中的策略變量來讓rails每次都從新載入他們。詳細rails的文檔。
使用Rake來運行 specs 注意到rake任務不能使用快速Rails_spec命令--就是說只能使用標準的spec。同時咱們注意到它預設的都是以_spec結尾的文件,因此你必須聽從以下的約定。 注意到你能夠經過編輯sepc/spec.opts文檔來配置傳給RSpec的選項。 那運行全部的spec(包括plugins)的代碼是: rake spec rake spec:app 包括plugins在內的specs: rake spec:all 你也可單獨運行 models、controller,view,helper或是plugin的specs: rake spec:models rake spec:controllers rake spec:views rake spec:helpers rake spec:plugins 查看rake中全部的RSpec任務: rake --tasks spec