[Rails] 寫測試初體驗

陳漢庭
Oct 16, 2020

--

工作大約一年以後,才開始自己從頭寫測試,之前只有改過vcr跟webmock而已。目前寫測試的功力還有待加強,但自從體會寫測試之後,心裡感到很踏實,比較不害怕自己寫壞自己的code,也不用擔心別人改壞了。

這是目前我所知道安裝測試用的gem。這些gem並不是全部都用過,個人對vcr, webmock, selenium, capabara就比較陌生。目前比較常用的只有factory_bot_rails, ffaker, rspec-rails等

group :test do
# Adds support for Capybara system testing and selenium drive
# Easy installation and use of web drivers to run system tests with browsers
gem
'capybara', '>= 2.15'
gem
'factory_bot_rails'
gem 'ffaker'
gem 'rails-controller-testing'
gem 'rspec-mocks'
gem 'rspec-rails', '~> 4.0.0.beta'
gem 'selenium-webdriver'
gem 'simplecov', require: false
gem
'webdrivers'
gem 'vcr'
gem 'webmock'
end

執行測試

如果沒有辦法成功執行測試就沒有意義了,下列為執行測試的範例指令。總之只要把rails的環境切到test就可以了(環境的部分可以查看專案的config/environments資料夾看專案有什麼環境)

rails db:migrate RAILS_ENV=test
bundle exec rspec ./spec/controllers/login_controller_spec.rb
bundle exec rspec ./spec/controllers/login_controller_spec.rb:22

資料夾

RSpec的資料夾結構如下圖,所有放在spec底下的都是測試資料。Spec factories為產假資料專區,裡面可能會有member.rb, product.rb, cart.rb…等等,分別對應的為會員、商品、購物車之類的。controllers, models, serializers資料夾分別對應controllers, models, serializers的單元測試。目前對於services, support, vcr還不熟悉,但有看過有人會把假api放進support裡面。rails_helper, spec_helper則是給_spec檔引入用。

依照慣例,專案所有欲測試的檔案檔名都為_spec結尾。裝了rails-controller-testing(這篇有更多介紹),controller的部分可能可以不用加,但由於專案的慣例都已經加了,所以我自己也按照了專案的慣例加了_spec,並加type: :controller的meta data。

假資料

產假資料所使用的gem為 factory_bot_rails, ffaker。

factory_bot_rails: 產資料用的
ffaker: 專門產生假資料(不局限在測試, 在seeds.rb, rake也可以用)

ffaker跟faker都是rails裡面產假資料的gem,而我所使用的專案引入的gem為ffaker。ffaker有些好玩的地方可以用(參考連結)。以下為使用ffaker的一些範例:

FFaker::Name.name        #=> "David Cao"
FFaker::Internet.email #=> "qichunren@cqror.com"
Faker::NameCN.first_name # => 鑫洋
Faker::NameCN.last_name # => 禹
Faker::NameCN.name # => 俊伶漫

FactoryBot

下列程式碼為商品相關的假資料。下列的trait可以讓我們不用重複寫code,這篇官方文件很詳細講了trait如何使用,總之我們可以透過trait來客製化我們的假資料。

在寫這支FactoryBot的時候踩了一個雷(參考連結:這裡),sequence內部要寫symbol。以專案來說,sequence(:name)是對的,而sequence(name)是錯的

最重要的是如何使用FactoryBot,通常我們會在spec這樣寫。下列第6行用途創建20筆資料用,:product, :collectable_product分別對應上面的product, trait: :collectable_product。

補充一下如果沒有使用trait的話,我們就得使用block去改寫原本FactoryBot.product的資料(參考連結:這裡)。長相如下:

Controller 測試

Get #index spec

首先前面的測試為分頁功能測試,再來才是資料比對測試。個人認為在做資料比對時,不用比對全部的資料,只要重要資料的筆數跟一些關鍵欄位內容一樣就可以了。

這邊說一下除了assigns以外,我們還可以使用sessions、flash、cookies。一般的CRUD使用assigns、flash就夠用了,但若要實作登入的話要會的東西可能就要比較多一點。

POST #create spec

待更新…

DELETE #destroy spec

待更新…

附帶小知識

Spring常常會將我們不需要的東西先預載入到後台,導致執行migration, rails s等會發生問題。當下了rake指令或者rails console出問題的話(以我來說遇到的狀況為rails console切到本地環境還是會連到測試站),可以使用指令:spring stop。spring參考文章可以看這篇文章,或者也可以參考官方文件

參考文章

Basic:let/let!/subjectDigital Ocean教學(推薦)連結(詳細)連結(詳細)連結
FactoryBot:官方多對多關聯Trait使用方式TraitTraitbuild_list
Controller驗證:連結(Nic)連結(Leon)Type: :requestWith paramsxdite連結
登入驗證:Login+Capytbara

--

--

陳漢庭

由於零散的紀錄過了一段時間之後就看不懂了,於是為了強迫自己用故事的方式記錄學到的東西,就開啟我的發文之路。