今天會開始介紹許多好用的 matcher
也就是配對子,從開始到現在我們都只使用過 eq
這種用法
其實還有很多有趣的 matcher
可以使用!
今天會介紹三種不同的 matcher
但又很相似的,分別是 eq
eql
be
!
eq Matcher
eq
是我們最常使用的 matcher
,其概念也非常簡單,就是單純的比較 value,而不比較 type !
可以用一些示範來比喻一下!
RSpec.describe "eq matcher" do
let(:a) { 5.0 }
let(:b) { 5 }
it 'only tests for value' do
expect(a).to eq(5)
expect(b).to eq(5.0)
expect(a).to eq(b)
end
end
這會是一個全部通過的情況!我們也說過 eq
只看值,不看型別。
為什麼會這樣說呢?因為其實在 Ruby 的世界中 5
and 5.0
兩個是屬於不同的類別!
若是在 IRB 中試試看:
> 5.class
> Integer
> 5.0.class
> Float
在 Ruby 的整數和浮點數是不同的類別,自然而然也不會是同一個 type!
但 eq
會略過型別的比對,專注在值是否吻合!
而一直強調型別,那會根據型別來判斷的 matcher
是哪個呢?
eql Matcher
雖然只差了一個 l
的字母,但在處理的嚴謹度上就完全不相同了!
如果一樣使用剛剛的範例,但改用 eql
來看看會發生什麼事情?
RSpec.describe "eql matcher" do
let(:a) { 5.0 }
let(:b) { 5 }
it 'tests for value and type' do
expect(a).to eql(5)
expect(b).to eql(5.0)
expect(a).to eql(b)
end
end
沒通過的結果:
他會告訴你,5
和 5.0
是不相同的東西,測試不通過!
你會想說,這樣有什麼差別啦,現實世界中 5 和 5.0 有什麼不一樣嗎?
但情境如果是在處理精密的匯率或是稅率等等,使用 eq
來做 matcher
是不是會有一點草率呢?
使用 eql
能夠幫你在撰寫方法的時候考慮得更多!也可以想像成嚴格模式~
因為它必須是 相同的 value 以及 相同的類別 才能被認定為相同!
接下來我想介紹更嚴格的一個 matcher
,他不只要你是同一個型別,他還要你是同一個物件!
equal Matcher & be Matcher
會放在一起講的原因是 equal
等同於 be
,所以接下來我們會一起示範這要怎麼用!
但在放上範例之前,想先提兩個概念:
equality
意思是在確認兩個物件在基本的設計上一樣的!
identity
意思是在確認兩個物件是同一個物件!
為什麼會講這樣的概念呢?因為 equal
就是 identity
的概念,而上面的 eq
eql
都像是 equality
的概念!
我們換個類比的方法,假設在一條大街上,我和隔壁的鄰居蓋了一間一模一樣的房子 ( 是真的一模一樣,包含窗框、草皮、房門等等 )
你心裡會說,這兩個房子長得一模一樣欸!但你不會說這是同一個房子,對吧?
就算他們在怎麼像,像到完全看不出來差別,你還是能用地址來做判斷,他們還是兩間房子!
等等示範的 equal
就是在幫你檢查是不是同一個地址的意思!
而 eq
eql
都只是看看照片說,這兩個根本一模一樣嘛~
廢話不多說,我們直接上 Code 吧!
RSpec.describe "equal matcher & be matcher" do
let(:a) { [7, 7, 7]}
let(:b) { [7, 7, 7]}
let(:c) { a }
it "test for object identity" do
expect(a).to eq(b)
expect(a).to eql(b)
expect(a).to equal(c)
expect(a).not_to equal(b)
end
end
上面是一個會全部通過的測試!
這邊的 c
變數,指向 a
變數,這代表著什麼?
我把我家的地址填得和你家地址一樣,這兩個會指向在同一個地方的物件!
而 a
和 b
在值以及型別上來看,都一模一樣,但他們在記憶體中的地址卻不相同,我們可以故意讓測試壞掉來看看 OutPut 是什麼?
我們讓 a equal b
來試試看!
錯誤的提示:
可以看到兩個在 Array
的記憶體位置是不相同的 ( 一個是 2800
, 一個是 2820
),這就像上面舉例有關房子的案例一樣,雖然長得一樣,但終究是兩個個體!
下面的提示也有告訴你,這是在比較物件的 identity
!
剛剛範例上都使用
equal
,但其實你也可以用be
達到一樣的效果
結語
重新複習一下三者的不同之處!
eq
:單純比較值,不在意型別
eql
:比較值以及型別
equal 以及 be
:比較值,型別,記憶體位置(是否為同一個物件)
希望以後大家在使用的時候,可以根據要測試的嚴謹程度來決定要使用哪一個 matcher
這三個都是非常基礎的 matcher
但卻常常不知道錯在哪,希望這篇文章可以幫助到你