RSpec 在節省程式碼這塊可以說是不遺餘力,甚至連常常使用到 example 都可以收納在一個檔案中再引入來使用!
Shared_examples
我們先來舉一個極端一點的例子,假設你在不同的測試檔案中,都剛好要測試 subject 的長度好了!
舉例
ruby
1 2 3 4 5 6 7 8 9 10 11
RSpec.describe Hash do
subject {{a: 1, b: 2, c: 3}}
end
RSpec.describe Array do
subject {[1, 2, 3]}
end
RSpec.describe String do
subject {"abc"}
end
可以想一下上面若是三個不同的測試檔案,想必我們就會正常的寫:
舉例
ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
RSpec.describe Hash do
subject {{a: 1, b: 2, c: 3}}
it "return length of subject" do
expect(subject.length).to be(3)
end
end
RSpec.describe Array do
subject {[1, 2, 3]}
.....
end
RSpec.describe String do
subject {"abc"}
.....
end
RSpec.shared_examples "Object with three elements" do
it "return length of subject" do
expect(subject.length).to eq(3)
end
end
這樣我們就建立好了一個可以被分享的 example,至於要如何使用呢?
我們只要引入這個 example 最上層的敘述就可以了!所以改寫一下我們原本的範例:
引入使用
ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14
RSpec.describe Hash do
subject {{a: 1, b: 2, c: 3}}
include_exmaples "Object with three elements"
end
RSpec.describe Array do
subject {[1, 2, 3]}
include_exmaples "Object with three elements"
end
RSpec.describe String do
subject {"abc"}
include_exmaples "Object with three elements"
end
畢竟 example 這種東西比較客製化,但如果是 shared_context 就可以放比較多設定的部分,物件等等…
直接用程式碼應該會更好懂一點:
shared_context
ruby
1 2 3 4 5 6 7 8 9 10 11
RSpec.shared_context "common_burger" do
before do
@big_mac = Burger.new("Beef", "Cheddar")
end
def shrimp_burger
@shrimp_burger = Burger.new("Shrimp", "Mozarella")
end
let(:pork_burger) { Burger.new("Pork", "Pecorino")}
end
這時候如果我們發現我們在設定物件的時候不停的重複,我們就可以把重複的物件蒐集到 shared_context 裡面,然後在 include 進來也一樣!
就像範例中一樣:
實際使用
ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
RSpec.describe Burger do
include_context "common_burger"
it "return shrimp" do
expect(shrimp_burger.meat).to eq("Shrimp")
end
....
end
RSpec.describe Store do
include_context "common_burger"
it "have big mac" do
expect(@big_mac.meat).to eq("Beef")
end
....
end
我們不用在上方堆疊一大堆的 let 或是 before hooks 這類的東西,我們可以在很多的測試檔中 include 進來使用!