RSpec 是 Rails 的其中一種測試框架,深受國外社群的愛戴,它的撰寫方式簡單易懂,非常好上手;語意化的設計讓測試代碼變得直觀,即便是初次學習的工程師也能夠迅速理解。
然而,台灣關於 RSpec 的文獻實在不多(找過比較完整的介紹是 ihower 的實戰聖經),加上 RSpec 還在發展中,不同派別的語法和 convention 很容易混在一起,要釐清它們並整理出一個最簡單可行的版本實在有些因擾。 但其實都沒想像中的困難,看完下面的敘述,你也能立刻寫出一個可以運行的測試代碼。
設定一個 RSpec 測試環境
由於 RSpec 不是 Rails 預設的 test framework ,在進行測試代碼開發前,我們必需先準備好測試環境。
安裝 rspec-rails 套件
在 Gemfile 裡將 rspec-rails 設定在 development 和 test 的 group 底下,並執行 bundle install
的指令,它會自動安裝好所需的套件。
group :development, :test do
gem 'rspec-rails', '~> 3.0.0.beta'
end
建立 rspec-rails 基本設定
執行 rails generate rspec:install
的指令,它會自動新增 RSpec 所需的檔案和設定。
#=> create .rspec
#=> create spec
#=> create spec/spec_helper.rb
建立一個 test 專用的 database
在 database.yml 中設定 test db 的參數
development: &default
adapter: mysql2
encoding: utf8
database: blog_development
host: localhost
username: root
password: ""
test: &TEST
<<: *default
database: blog_test
接著執行 rake db:test:prepare
,rake 會根據 schema 新增一個測試用的 database。
學會 RSpec 的基礎語法
RSpec 提供很多 sugar syntax 和 features 讓我們寫出漂亮的測試代碼,這些語法經常會對初學者的腦袋造成混亂。 其實只要幾個基本的語法,就可以寫出簡單的測試。 下面將以 board 為例,說明如何運用它們
# title :string(255)
# description :text
class Board < ActiveRecord::Base
end
執行 rails g rspec:model board
指令,它會在 spec 的 model 資料夾底下新增一個 board 的 spec 檔案。
require 'spec_helper'
describe Board do
pending "add some examples to (or delete) #{__FILE__}"
end
context 與 describe
context 和 describe 都是用來宣告 example group 的語法,一般會將 describe 當作測試 feature 的 group。
describe "#is_news?" #=> 井號代表 instance method 的測試
describe ".find_by_title" #=> 句號代表 class method 的測試
而 context 通常當作 condition 的 group。
context "when title is empty"
context "when title is News"
it
每個 it 都代表一個 test example,而測試代碼都必需在 it 的 block 裡宣告才會被執行 ; 在尚未填入 block 之前,it 只會列在 pending 的清單裡。
describe Board do
describe "#is_news?" do
it "returns true when eq news"
end
end
OUTPUT
expect && eq
expect 和 eq 是 test example 裡很常被用到的語法,通常是 expect(預期的對象).to eq(預期的結果)。
由於 blog_test 裡面完全沒有資料,我們必需先產生 Board 的資料再來驗證。
it "returns true when eq news" do
@board = Board.create!(:title => "news")
expect(@board.is_news?).to eq(true) #=> 在這裡也可以用 be_true 來表示
end
OUTPUT
當 example 測試跑完,RSpec 會顯示 example 的數量和失敗的數量,failures 等於 0 的情況才算測試成功。
學會判斷 RSpec 的測試失敗 message
稍早我們已經知道測試成功的 message,另一方面也必需了解如何從錯誤的訊息中判別,以下圖為例
Red 代表某些 example 失敗了
message 會將失敗的代碼上色並且提供相關的訊息,只要見到紅色的文字出現,就代表有 example 失敗了。
列出失敗的行數與目的
message 會提供失敗的代碼行數和該代碼的測試目的,讓 RD 能夠迅速理解代碼的邏輯。 如圖中的 describe,我們很清楚的知道,當 @board 是 news 的時候 is_news? 應該要 return true。
expect 的 value
message 會印出 expect 的真實 value,例如 @board.is_news? 預期會 return true,但實際上獲得的 value 卻是 false。