have_attributes matcher
這個 matcher
很清楚明瞭的告訴你是來測驗物件的屬性的!
直接用範例來介紹一下:
class Burger
attr_reader :meat, :cheese
def initialize(meat, cheese)
@meat = meat
@cheese = cheese
end
end
RSpec.describe "have_attributes matcher" do
describe Burger.new("Beef", "Cheddar")
it "checks attribute and value" do
expect(subject).to have_attributes(meat: "Beef")
expect(subject).to have_attributes(cheese: "Cheddar")
end
it { is_expected.to have_attributes(meat: "Beef") }
it { is_expected.to have_attributes(cheese: "Cheddar") }
end
end
程式碼針對漢堡這個類別來進行測試,分別檢驗他的 meat
& cheese
屬性所給予的值!
進而判斷這個屬性是否存在,其實這個真的很簡單,也沒有真的比較特殊的寫法,所以就這樣簡單的用範例來介紹一下。
include matcher
接下來這個對於有學過 Ruby 的人來說,應該是超級好用的一個語法!
而在 RSpec 中也是異曲同工之妙,就是檢查 字串
陣列
Hash
中,所包含的字串、數字或是 key & value
這樣的用法!
就用範例來更清楚的了解一下:
RSpec.describe "include matcher" do
describe "yummy burger" do
it "checks substring" do
expect(subject).to include("yummy")
expect(subject).to include("burger")
expect(subject).to include("bur")
end
end
describe [1, 5, 7] do
it "checks inclusion value in the array" do
expect(subject).to include(1)
expect(subject).to include(5)
expect(subject).to include(7)
expect(subject).to include(7, 5)
end
end
describe { t: 5, y: 7} do
it "checks key or key value pair" do
expect(subject).to include(:t)
expect(subject).to include(:t, :y)
expect(subject).to include(t: 5)
end
it { is_expected.to include(:y)}
end
end
這個的用法也很簡單,有個重點就是他不看順序的,主要是看內容物來覺得測試通過與否!
raise_error matcher
這個 matcher
就是拿來測試噴錯的結果的,沒錯!工程師當然要能夠預期錯誤的結果,有些時候的錯誤是預期的,所以我們當然也要加入測試。
如果是寫在 Rails 的專案中,確實還蠻常使用到的,在某些特殊的情況需要加入 begin...rescue
時,就會寫到了。
那還是來簡單的示範一下狀況:
RSpec.describe "raise error matcher" do
def wrong_method
gggg
end
it "check error being raised" do
expect { wrong_method }.to raise_error
end
end
首先講寫法上面,記得之前提過,若是要執行方法等等,要記得使用 { }
來做執行的動作。
再來是你能預期這個方法會出現什麼樣的錯誤嗎?
先看看測試的結果:
通過了測試,但是官方希望你可以更詳細的解釋這是一個什麼樣的 Error,所以只要在後方加上:
expect { wrong_method }.to raise_error(NameError)
這樣就可以看到正常的 Output 了,當然你也可以在設定檔裡面關閉這個提醒,但還是寫的仔細好一些。
甚至還可以自己建造錯誤類別來繼承原本的錯誤類別,執行自己的錯誤,這也是很常見的使用方式:
class CustomError < StandardError; end
it "rails himself" do
expect { raise CustomError }.to raise_error(CustomError)
end
respond_to matcher
這個 matcher
主要在測試一個 Interface
所回應的方法!
也可以說成類別,一個類別會有的方法,以及所需的參數等等…
看看範例就能了解,我們先建造一些類別來使用:
class Burger
def eat
p "yummy!!!!"
end
def discard
p "So bad..."
end
def buy(money)
p "i will spend #{money} to buy this good shit!!"
end
end
RSpec.describe "respond_to matcher" do
describe Burger do
it "checks an object respond method" do
expect(subject).to respond_to(:eat)
expect(subject).to respond_to(:eat, :discard)
expect(subject).to respond_to(:eat, :discard, :buy)
end
it "checks method and arguments" do
expect(subject).to respond_to(:buy).with(1).arguments
end
end
end
寫起來有點多,但其實就是測試這個類別回應的公開方法而已,注意!!私有方法是沒辦法被 respond_to
的。
畢竟都已經是 private
還可以公開的回應,那好像也怪怪的!
satisfy matcher
這個 matcher
超級好用,而且彈性超大~
不像前幾個 matcher
基本上都是 Ruby 的語法轉型變成 RSpec 的語法,這個是獨有的!
先看看示範:
RSpec.describe "satisfy matcher" do
subject { 'level' }
it "is a palindrome" do
expect(subject).to satisfy { |value| value == value.reverse }
end
it "can do something in block" do
expect(10).to satisfy { |value| value / 2 == 5 }
end
it "can add custom message" do
expect(100).to satisfy("bigger than 50") do |value|
value > 50
end
end
end
它就是一個只要能夠在 block 裡面滿足條件,就可以通過測試的一個好東西!
彈性很高,可以在裡面寫入很多 Ruby 的語法,在測試的時候也比較不會綁手綁腳的。
客製化訊息也會在 Output 上一併出現,這個 matcher
先推推!
compound expectation
這個就是一個 expectation
雖然蠻無聊的,想說就也提一下好了。
簡單來說就是合成你的 RSpec 語法,要 and &&
或是 or ||
對比上你的複數 matcher
才能夠通過:
RSpec.describe 30 do
it "test for multiple matchers" do
expect(subject).to be_even.and be > 25
end
describe [1, 5, 7] do
it "can use or" do
expect(subject.sample).to eq(1).or eq(5).or eq(7)
end
end
end
就如範例所示,可以串接你的 matcher
並且使用 and
或是 or
方法來連接!
結語
終於結束了滿滿的 matcher
,接下來就進入到一開始很難理解的 double
以及 stub
的章節!
也是我覺得超級實用的領域,真的能夠辦到很多有趣的事情!