還記得我們使用 let
方法來實作一個物件讓我們可以快速地使用!
但有沒有什麼好方法可以讓我不要想物件的名字?可能因為我有取名的障礙或是英文真的太爛了!
甚至我連 let
都懶得寫,實在是太懶惰了…
有! RSpec 有個有趣的方法叫做 subject
,他會自動根據整個 RSpec 最上層的類別名稱來決定 subject
該是什麼!
Subject
剛剛的說法也都比不過一個實際的例子來得實際,看看以下範例!
RSpec.describe Hash do
it "should be empty" do
expect(subject.length).to eq(0)
end
end
這是 output 的結果:
現在一定是一頭霧水,想說這個 subject
到底是在哪裡?我們甚至沒有宣告它啊?
這就是 RSpec 提供的便利方法,如果最上層 RSpec.describe
後方接的是類別,那 subject
就會依照這個類別的預設值去做 new
的動作。
我們可以把 subject
給印出來看看!
RSpec.describe Hash do
it "should be empty" do
p subject
p subject.class
expect(subject.length).to eq(0)
end
end
output 的結果:
所以我們可以想像,它在上方幫我們做了:
let(:subject) { Hash.new }
這是動態產生的,根據我們提供的類別來建立物件!是不是很方便呢?
加上他和 let
一樣,在每一個 example 中都是獨立的,不會有污染物件的情形,可以放心地使用!
加入初始值的 Subject
剛剛示範的是完全乾淨的一個物件,但如果我們想要建立一個有不一樣初始值的 subject 該怎麼做呢?
馬上來示範一下:
RSpec.describe Hash do
subject do
{a: 3, b: 4}
end
it "should be empty" do
expect(subject.length).to eq(2)
end
end
其實很簡單,但如果不想要叫做 subject
呢?
只要在後面加入變數的命名就可以了!
RSpec.describe Hash do
subject(:robert) do
{a: 3, b: 4}
end
it "should be empty" do
expect(subject.length).to eq(2)
expect(robert.length).to eq(2)
end
end
至於為什麼要這樣用?使用 let
還不是一樣,何必浪費時間寫三行呢?
你說的沒錯,用 let
的效果也是一樣,但 subject
有其他更魔法的方法可以使用,等等也會一併介紹,會讓寫出來的 Code 優雅到不行!
在介紹黑魔法之前,先來介紹另一個也很有趣的語法。
Described_class
剛剛介紹的是 subejct
的好用之處,這次介紹的 described_class
可能不一定會用到,但在改大量程式碼的時候很有用!
先用範例來解說一下:
class Burger
attr_accessor :beef, :cheese
def initialize(beef, cheese)
@beef = beef
@cheese = cheese
end
end
RSpec.describe Burger do
subject { Burger.new("Beef", "Cheedar") }
let(:pork_burger) { Burger.new("Pork", "Cheedar") }
it "...." do
....
end
end
這邊有個漢堡的類別,假設需求今天下來是要更改這個 Burger 類別的名稱,怎麼辦?
任務是把 Burger 改成 GoodBurger 這個名字,若是只有兩三行,那倒是沒什麼問題,但如果是 100 行呢? 要怎麼做?
這時候 described_class
就可以派上用場,若是一開始都用這樣的寫法就好了:
class GoodBurger
attr_accessor :beef, :cheese
def initialize(beef, cheese)
@beef = beef
@cheese = cheese
end
end
# 我們只需要更改這邊的類別名稱就可以了!
RSpec.describe GoodBurger do
subject { described_class.new("Beef", "Cheedar") }
let(:pork_burger) { described_class.new("Pork", "Cheedar") }
it "...." do
....
end
end
described_class
雖然不是一個很常使用的東西,但它就是可以根據你上面放置的類別來動態產生物件,而且只需要改類別名稱就能夠一次跟上!
說不定在某些時候會幫助到你!
我只要寫一行
前面有提到使用 subject
的小小好處,就是可以讓你只要寫一行!
直接先看程式碼:
RSpec.describe 5 do
it "should be 5" do
expect(subject).to eq(5)
end
context "one line syntax" do
it { is_expected.to eq(5) }
end
end
這是 output
第三行是很常使用的寫法,所以沒有什麼問題。
但第七行就是 subject
的神奇之處, is_expected
這個方法本身的主詞就是 subject
,所以可以這樣子就寫完範例。
不覺得看起來整個就超級 Ruby 的嗎?,該省的都要給我省下來,越短越好!
希望這可以讓你在寫某些簡單的 example 中可以派上用場!
Don’t Repeat Yourself 能不要重複撰寫就盡量節省!
結語
今天介紹了 subject
& described_class
還有一行流的寫法!
不一定是常常會使用到,但都是 RSpec 很基礎的語法,至少先記在腦袋裡面,想起來再去查資料就可以了!
現在介紹的都是整理單個測試的程式碼,但如果在不同的測試有著相同的 example 呢?