blog-banner
五倍學院
撰文者/Melissa

2021-12-01 Views: 1817

規劃 FactoryBot 小技巧,你的測試可以做得更好

actoryBot(前身為 FactoryGirl)為知名軟體方案解決公司 ThoughtBot 所開發,其用途非常地單純,就是讓使用者可以輕鬆地生產測試用資料。
而使用 FactoryBot 的方式也相當簡單。只要安裝了 Gem 並新增一個 Factory,就可以產生資料。

Factory 長這個樣子

然而雖然 FactoryBot 相當好入門,但是當你在規劃 Factories 的時候,有一些細節必須要注意,否則在未來程式變得複雜化的同時,在測試上恐怕會衍生出許多不必要的麻煩。
1.避免指定非必要欄位
非必要欄位有可能是自動生成的欄位(有 Default 值,例如 created_at),或是不影響資料庫保存的欄位(不需要驗證、可以為 Null 的欄位),倘若這些資料在測試中佔有重要的一環,則使用 trait 來指定。
舉例來說,假設你有個測試要找出加入超過兩年以上的 User,那麼可以寫成這個樣子:

最忌諱的就是在限制 Unique 的欄位直接賦值,千萬不要這麼做!因為當你未來要在一個 Test Case 裡面生成兩筆以上的資料的話,就會產生驗證錯誤而無法儲存資料。

2.指定有限制欄位有方法
倘若我們真的有需要在 Unique 的欄位賦值,有什麼好方法嗎?你會有以下幾種做法。

  • 手動賦值 如果只是偶爾需要賦值的情況下,我會建議直接在生產資料的時候手動賦值,例如 FactoryBot.create(:user, id_number: 'E1222333444'),如此一來比較容易掌握生成的資料。
  • 利用 Sequences 這是 FactoryBot 所提供的一個方法,可以以 auto incremental 的方式產生資料。

如此一來,每當用 FactoryBot 產生 User 的時候,他就會自動生成不重複的 id_number,會從 E1222333401, E1222333402 這樣的形式來新增。
不過這樣的做法會有一個問題,假設 id_number 有限制其字元數必定為 11,那麼當我們生產到第一百個 user 的時候,它的數值就會變成 E12223334100,會多出一個字元。為了避免這樣的情況,我們可以使用 Ruby 的 #cycle method,將它改成這樣子:
sequence(:id_number, ('01'..'99').cycle) { |n| "E12223334#{n}" }
如此一來,當生產到第一百個 User 的時候,它就會自動迴圈變回 E12223333401 了。
1.善用 Trait 讓你的資料更淺顯易懂
上面有提到利用 trait 來指定非必要欄位,你也可以用 Trait 來讓你的程式碼可讀性更高。舉例來說,我們有一個欄位叫做 status 用來記錄會員的帳號狀態,那麼在定義 Factory 的時候便可以利用 trait 來標示這些狀態。

這樣的做法不僅讓你的 Factory 變得乾淨,同時當你在生成資料的時候,也可以一目瞭然。特別是當你的測試非常需要各種不同的狀態下變動時,能夠更清楚明白測試的目標和內容。
2.搭配 Faker 隨機生產資料 Faker 是對於命名能力缺乏的工程師的一種救贖。它的能力作用就是生產隨機資料,從一般的信用卡卡號和人物的人名,到權力遊戲和 Pokemon 的角色,它都可以幫你生出來,用來瘩配 FactoryBot 生產測試資料,可謂妙不可言。
不過,當使用 Faker 搭配 FactoryBot 的時候,有些事情必須要注意。首先是在寫 Factory 的時候,我們必須用 block 來賦值給欄位,假設我們用參數的方式賦值的話,他只會隨機產生出其中一個結果,意味著如果你的欄位是 unique 的話,產生第二筆以上資料就會發生錯誤。

另外一點則是,有些 Faker 內的 Seed 是有限的,遇到欄位是 Unique 的情況下必須謹慎使用 Faker,否則在建立愈多資料的情況,愈有可能隨機到相同的值造成資料庫的寫入錯誤。因為這種問題有隨機性,也比較難除錯,因此要盡可能避免這樣的狀況,當你發現某個測試常常出現這樣的情況,那就乾脆地手動賦值吧!

小結


FactoryBot 是個功能單純而且容易操作的套件,不過針對愈複雜的測試情況和應用也有著相當進階的功能,在這篇文章中提出一些初始規劃 Factory 時應該避免或者注意的地方,希望拋磚引玉能讓更多人知道 FactoryBot 的好處及妙用。

快來認識 五倍學院
五倍學院
五倍學院
我們喜歡 Ruby 這個程式語言,除了積極經營 Ruby 技術社群之外,同時也提供【技術諮詢】、【企業內部培訓】、【教育訓練】等服務。另外也努力開班授課,協助更多人進入程式開...