BDD 作為一種設計方法,可以有效的改善設計,并在系統的演化過程中為團隊指明前進方向。
RubyOnRails中具體使用的工具叫cucumber,這部分也可完全做客戶需求的代替,是敏捷開發重要基石,不過本文不是主要講這個,到現在還沒接觸到什么cucumber的資料
二. 什么又叫測試驅動開發,英文全稱Test-Driven Development,(簡稱TDD)
測試驅動開發,英文全稱Test-Driven Development,簡稱TDD,是一種不同于傳統軟件開發流程的新型的開發方法。它要求在編寫某個功能的代碼之前先編寫測試代碼,然后只編寫使測試通過的功能代碼,通過測試來推動整個開發的進行。這有助于編寫簡潔可用和高質量的代碼,并加速開發過程。
RubyOnRails中具體用到的工具叫Rspec,也是本文主要講的內容
三. 一般開發流程(項目周期 )
在基于BDD開發模式的項目中,以Rails項目開發為例,有如下步驟:
1、 對一個項目立項后,首先進行故事分解。要對系統故事分解,要求我們做到基本的需求分析和對系統的概要設計。
2、 專注于一個用戶故事,對其進行詳細定義,這一階段也就是我們編寫RSpec測試用例的階段。通過分析用戶故事和用戶場景的方式對系統的行為進行詳細的定義,把定義寫在我們的測試用例中。在這一階段,包括了我們的傳統的軟件工程周期中的需求分析和詳細設計階段,需求分析體現在分析系統的行為上,詳細設計體現在用例編寫時需要為系統實現定義大量的接口,這一點下邊細講。
3、 對于該用戶故事,實現View層:
3.1、運行RSpec測試用例,結果失敗;
3.2、編碼實現該view;
3.3、重新RSpec運行測試用例,通過;
3.4、重構代碼;
4、 對于該用戶故事,實現controller層,重復3.1-3.4的過程。
5、 對于該用戶故事,實現model層,重復3.1-3.4的過程。
6、 重構三個層次的代碼,完成該用戶故事。
7、 重復3-6的過程,完成系統其他用戶故事。
8、 系統集成,集成測試,確認測試,beta測試等。
9、 系統交付及后期維護。
這個過程圖示如下:
這里強調了按照view、controller到model的順序來做開發,這是BDD鼓勵從外向里的方式來開發程序,先實現與用戶直接交互的view層,然后是核心業務層controller,最后是與數據庫交互的model層,BDD不但是我們開發程序中運用的一種技術,同時也可以盡早的將系統的用戶接口體現出來,體現系統的商業價值,對于開發,用戶與系統交互時的行為是系統的核心業務,先將用戶接口開發出來,有助于我們專注于實現核心業務,而不浪費精力于其他方面。
四. 配置與Rspec實踐
1.安裝與配置
如果是已有項目直接在gemsfile里面配置即可如下 如(由于筆者使用的jruby版本比較低)
group :development, :test do
gem "database_cleaner"
gem "rspec-rails"
gem "cucumber-rails"
gem "webrat"
gem "rspec-mocks"
gem "spork",'~> 1.0rc'
gem "factory_girl",'~>2.6.4'
gem "factory_girl_rails",'~>1.7.0'
end
主要配置插件有
rspec-rails
cucumber-rails
factory_girl_rails(模擬大量測試數據)
在這里配置好后可直接bundle update 自動安裝相關插件
當然也可以用gem install XXXXX方式安裝。
最后形成的目錄結構如圖
小技巧 如果使用時rubymine 這個IDE,你可以利用他的tools工具選項里面bundle操作,或是quick install gem 來安裝和維護插件
2. control部分測試實踐(主要運用了stub的打樁技術)
代碼如下
before(:each) do
@metadatum = mock_model(Metadatum)
@metadatum.stub(:subscribe_to_the_number_of).and_return("1")
@metadatum.stub(:save).and_return(true)
end
it "Get index should not nil" do
get "index"
response.should_not be_nil
assigns[:metadatas].should_not be_nil
end
首先我們可以看到一個一般Rspec測試主要用到的格式
describe “測試描述”do
befor(:each) do
每個測試用列都需要執行的內容
end
it “測試用例說明”do
具體測試代碼
end
end
控制器中response的返回結果可能不同,在筆者項目中主要用到幾種類型數據測試
redirect_to(重定向 )
在具體測試中我們可以這樣寫
response.should redirect_to(:action => :index)
對于flash數據我們要驗證他的內容我們可以這樣寫
flash[:notice].should eq('你預計得到的結果')
對于render的數據內容你可以用render_template 來接受如下
response.should render_template (:action中用到的鍵 => 具體的值 )
而對于action中調用action的時候,我們為了保證系統解耦性,所以需要截獲調用action和返回值,這時候我們可以用到mock
比如上面用到的
@metadatum = mock_model(Metadatum)
Metadatum.stub(:new).and_return(@metadatum)
@metadatum.stub(:subscribe_to_the_number_of).and_return("1")
@metadatum.stub(:save).and_return(true)
這幾句就是我們用來模擬Metadatum這個模型的方法
3.model的測試(主要運用factory_girl構建數據技術)
對于模型的測試我們主要運用factory_girl來做大量數據模擬,具體代碼如下
在..\spec\factories目錄下我們主要是構建測試數據
FactoryGirl.define do
factory :metadatum do
abstract "Administrative orders"
metadata_identifier "administrative"
metadatadate_update Time.now
resource_type "About administrative orders "
upload_state Date.today
online_source "orders"
publication_data Date.today
resource_degree ""
resource_id 1
resource_title 1
verify_enable 1
end
end
在我們具體model測試中調用這個數據方法如下
..\spec\models\metadatum_rspec.rb
before(:each) do
@metadata = Factory.create(:metadatum)
end
it "This 'verify_enable' should be 0 "do
@metadata.set_resource_type(0)
expect(@metadata.resource_type).to eq(0)
end
我這里用了expect這個斷言,一旦出現失敗的情況,就會在測試中體現出來,當然我們也可以用should這個方法來測試,那么最后一句就該這樣寫
@metadata.resource_type.should == 0
五.總結
經過一段時間的學習,自己大約摸到點測試的感覺,但是需要學習的東西還很多,自己在針對模型測試,只是在今晚才剛學習了factory一點東西,還有大量的沒有做到,針對view和gem測試部分還沒學習到,當然自己上面的東西也不一定全面和正確,關于測試學習部分我以后也會繼續維護。