在上一篇我們已經安裝好 rspec 也產出了 User model 接下來就開始嘗試寫測試摟!
我在 User 上多了幾個欄位接下來就可以針對以下欄位來做測試
2.6.6 :003 > User
=> User(id: integer, created_at: datetime, updated_at: datetime,
name: string, email: string, phone: integer)
我們可以先思考 name 這個欄位為必填的話測試可以怎麼寫?
require 'rails_helper'
RSpec.describe User, type: :model do
describe 'validations' do
context 'name must be present' do
it 'is not valid without a name' do
user = User.new(phone: '123', email: 'test@ck.com')
expect(user).not_to be_valid
end
it 'is valid with a name' do
user = User.new(name: 'ck', phone: '123', email: 'test@ck.com')
expect(user).to be_valid
expect(user.name).to eq('ck')
end
end
end
end
用上述例子可以看到有很多陌生的專有名詞,我們可以依依解釋
type: :model
=> 指定type 為 model,當然也有 controller、view、requestdescribe
=> 就是字面上的意思描述此區域的測試要測的內容context
=> 作用域其實與 describe 相同其實沒有太多差異只是describe的別名,主要是區隔規格it
=> 指每個測試案例expect
=> 最常用到的語法也是每個測試的精髓,你期望哪些東西會等同於你想像的樣子。比如:沒有名字那就期望這個user在建立時就是無效的
對於describe與context差異的朋友可以看看這篇 describe vs. context in rspec
According to the rspec source code, “context” is just a alias method of “describe”, meaning that there is no functional difference between these two methods. However, there is a contextual difference that’ll help to make your tests more understandable by using both of them.
如果我們跑一下這個測試會發現測試沒有通過
$ rspec spec/models/user_spec.rb
Failures:
1) User validations name must be present is not valid without a name
Failure/Error: expect(user).not_to be_valid
expected #<User id: nil, created_at: nil, updated_at: nil, name: nil, email: "test@ck.com", phone: 123> not to be valid
# ./spec/models/user_spec.rb:8:in `block (4 levels) in <top (required)>'
Finished in 0.12145 seconds (files took 4.03 seconds to load)
2 examples, 1 failure
Failed examples:
rspec ./spec/models/user_spec.rb:6 # User validations name must be present is not valid without a name
當 user 沒有 name 時應該要是無效的但他卻建立出來了
這時就會知道應該是在 model 的地方沒有補上 validate 導致測試沒通過所以我們到 models/user.rb
# user.rb
class User < ApplicationRecord
validates :name, presence: true
end
再跑一次測試 rspec spec/models/user_spec.rb
$ rspec spec/models/user_spec.rb
..
Finished in 0.12003 seconds (files took 4.19 seconds to load)
2 examples, 0 failures
我們第一個測試就大功告成了! 但也會發現怎麼建立起來這麼麻煩而且有重複的code 明天我們就使用 Shoulda Matchers 跟 FactoryBot 來優化測試吧!