Rails預設有三個執行環境,即development、test與production,有幾個檔案與這三個執行環境有關,config/database.yml中預設定義了三個執行環境所使用的資料庫設定:
- database.yml
development:
adapter: sqlite3
database: db/development.sqlite3
pool: 5
timeout: 5000
test:
adapter: sqlite3
database: db/test.sqlite3
pool: 5
timeout: 5000
production:
adapter: sqlite3
database: db/production.sqlite3
pool: 5
timeout: 5000
建立新專案時,預設就會產生development.sqlite3與test.sqlite3,後者是作為測試時的資料庫,其中的資料在每次測試時都會根據相關設定重建,確保每次測試的資料來源一致。config/environments中也分別有development.rb、production.rb、test.rb,分別作為三個環境的組態檔案。
Rails的應用程式通常與資料庫有密切互動,所以實際上進行測試時若存在相關模型測試檔案,就必須在資料庫中有對應的表格定義。例如 認識 Rails 測試 中的例子,如果已像 觀摩 Scaffold 中產生了Message模型,即使你指定執行rational_number_test.rb,也會發生以下錯誤,告訴你沒有對應的表格:
Loaded suite test/unit/rational_number_test
Started
RationaNumberlTest:
ERROR rational number addition (0.00s)
ActiveRecord::StatementInvalid: Could not find table 'messages'
/usr/local/lib/ruby/gems/1.9.1/gems/activerecord-3.1.3/lib/active_record/connection_adapters/sqlite_adapter.rb:439:in `table_structure'
ERROR rational number subtraction (0.00s)
ActiveRecord::StatementInvalid: Could not find table 'messages'
/usr/local/lib/ruby/gems/1.9.1/gems/activerecord-3.1.3/lib/active_record/connection_adapters/sqlite_adapter.rb:439:in `table_structure'
Finished in 0.007304 seconds.
2 tests, 0 assertions, 0 failures, 2 errors, 0 skips
在執行測試之前,得執行過rake db:migrate,產生schema.rb之後,再執行rake db:test:load,將schema.rb中的結構記錄載入測試資料庫,之後若有任何遷移變更,可執行rake db:test:prepare,將遷移變更載入測試資料庫,再執行相關測試。
來看看一個測試Message的例子:
- message_test.rb
require 'test_helper'
class MessageTest < ActiveSupport::TestCase
test "should not save message without name" do
assert !Message.new.save, "Saved the message without name"
end
end
這測試了Message儲存時,必須驗證name是否設定,接著修改Message定義:
- message.rb
class Message < ActiveRecord::Base
validates :name, :presence => true
end
如果在測試之前,資料庫中必須有某些既存的資料,那麼你可以定義fixtures,也就是範例資料,這是test/fixtures資料夾中定義YAML,例如:
- messages.yml
justin:
name: Justin Lin
title: About Java TWO 2012
content: When will it be?
momor:
name: Momor Huang
title: Kindle DX Arrived
content: As title
Rails預設會載入test/fixtures中的YAML,原因在於 認識 Rails 測試 中看過的,test_helper.rb中定義了fixtures :all(如果只想指定載入特定YAML,可以指定如fixtures :messages),以便進行單元測試與功能測試,載入的過程有:
- 移除資料庫表格中對應fixtures的資料
- 將fixtures中的資料重新載入表格
- 將fixtures中的資料載入對應變數
以上例而言,可以透過messages方法來取得對應的fixture,例如messages(:justin)可取得YAML中定義的資料,取得的物件是模型的型態,例如messages(:justin)就是取得Message物件。
fixture定義檔中,也可以使用Erb,內嵌的Ruby程式碼會先被處理。例如:
- messages.yml
<% sample_content = "blah..blah" %>
justin:
name: Justin Lin
title: About Java TWO 2012
content: <%= sample_content %>
momor:
name: Momor Huang
title: Kindle DX Arrived
content: <%= sample_content %>
實際上除了如上使用ruby指令逐一執行測試之外,也可以使用rake test執行所有已定義的測試,如果僅想執行單元測試,可以執行rake test:units,這會執行test/unit中定義的單元測試,類似地,執行rake test:functionals可執行test/functional中定義的功能測試,執行rake test:integration可執行test/integration中定義的功能測試。