1.為什麼寫測試
rails使得我們很容易就可以寫測試。在創建model和controller的時候,rails幫助我們創建了測試的骨架代碼。
通過簡單的運行你的測試代碼,你可以確保你的代碼在重構之後任然滿足需求的功能。
rails測試可以模擬浏覽器請求,這樣你就可以在不適用浏覽器的情況下測試應用的響應情況。
2.測試簡介
因為每一個rails應用都會和數據庫有大量的交互,因此你的測試也需要一個數據庫來進行交互。為了更好的寫測試,你需要知道如何建立數據庫,以及加載樣本數據。
2.1.三個環境
每個rails應用都有三個環境:生產,開發,測試。
在config/database.yml文件中包含這三個環境的數據庫設置。
如果你想要在測試數據庫中進行數據操作,你需要將開發環境的數據庫結構映射到測試環境。你可以執行下面的命令。
rake db:test:prepare
2.2.測試文件夾結構
在你使用rails new命令創建應用的時候,rails會幫你創建一個test文件夾,文件夾包含下面的內容。
root@web:/home/railsapp/login# ls -F test/
fixtures/ functional/ integration/ performance/ test_helper.rb unit/
unit文件夾存放針對model的測試,functional文件夾存放針對controller的測試,integration文件夾存放針對controller之間交互的測試,fixtures文件夾用來組織測試數據。test_helper.rb保存測試環境的配置信息。
2.3.Fixtures的內幕
一個好的測試,你需要建立一些測試數據。在rails中,你可以通過自定義fixtures來實現。
2.3.1.什麼是fixtures
fixtures允許你在測試運行之前,使用預定義的數據填充測試數據庫。fixtures是數據庫無關的,它是一種yaml格式。
當你使用rails g model創建新model的時候,就會在fixtures文件夾自動創建一個fixtures。
2.3.2.YAML
yaml對人是一種非常友好的描述數據的格式。這些fixtures的後綴是.yml。例如,users.yml。
# lo & behold! I am a YAML comment! david: name: David Heinemeier Hansson birthday: 1979-10-15 profession: Systems development steve: name: Steve Ross Kellock birthday: 1974-09-27 profession: guy with keyboard
2.3.3.內嵌erb
在yml中也可以內嵌ruby代碼,在加載fixtures之前會進行預處理。
下面的yml中就定義了一個變量earch_size。
<% earth_size = 20 %> mercury: size: <%= earth_size / 50 %> brightest_on: <%= 113.days.ago.to_s(:db) %> venus: size: <%= earth_size / 2 %> brightest_on: <%= 67.days.ago.to_s(:db) %> mars: size: <%= earth_size - 69 %> brightest_on: <%= 13.days.from_now.to_s(:db) %>
ruby代碼包含在<% %>中。
2.3.4.fixtures實踐
rails會自動加載fixtures文件夾中的所有fixtures。加載的步驟包括:
首先刪除表中已經存在的fixtures中的數據。
將fixtures中的數據加載到table中。
當fixtures數據加載到變量,你可以直接通過變量來訪問數據。
加入你有一個前面寫的uses.yml文件,就可以通過hash的形式來獲取用戶信息。
user = users(:david)
進而獲取user的各種信息。
user.name user.birthday user.profession
3.針對model的單元測試
在rails中,單元測試就是用來測試model的。
當你使用rails g model或者rails g scaffod命令的時候,會自動在test/unit中生成對應的單元測試。
# test/unit/post_test.rb require 'test_helper' class PostTest < ActiveSupport::TestCase # Replace this with your real tests. test "the truth" do assert true end end
請注意測試類繼承ActiveSuppoort::TestCase。
def test_the_truth assert true end
所有test開頭的方法都會被認為是一個測試,也就是說所有的測試方法都必須以test開頭。test_password,test_valid_password,testpassrod都是合法的測試名稱,都會在測試的時候自動運行。
3.1.做好測試准備
在運行測試之前,你需要確保測試數據庫的結構和開發環境一致。
rake db:migrate rake db:test:load
rake db:migrate用來生成開發環境的數據庫,並且更新db/schema.rb文件。rake db:test:load會根據db/schema.rb重新創建測試數據庫。你也可以執行rake db:test:prepare。
3.2.運行測試
$ ruby -Itest test/unit/post_test.rb Loaded suite unit/post_test Started . Finished in 0.023513 seconds. 1 tests, 1 assertions, 0 failures, 0 errors
你也可以通過-n參數來制定運行的測試。
rake test TEST = test/unit/user_test.rb
ruby -Itest test/unit/post_test.rb -n test_the_truth
4.測試controller的功能測試
4.1功能測試包含的內容
web請求成功了嗎?
user被轉到正確的頁面了嗎?
用戶是否authenticate成功?
響應中包含的對象是否正確?
是否在view中給用戶顯示了正確的內容?
4.2在功能測試中可以用到的請求類型
get
post
put
delete
head
4.3可以使用的四個哈希
assign
cookies
flash
session
4.4可以使用的實例
@controller,處理請求的controller。
@request,請求。
@response,響應。
5.集成測試
集成測試用來測試多個controller之間的交互。
rails g integration_test user_flows
# test/integration/user_flows_test.rb require 'test_helper' class UserFlowsTest < ActionDispatch::IntegrationTest fixtures :all # Replace this with your real tests. test "the truth" do assert true end end