before
用法比較像是在測試之前你需要哪些前置作業? after
就是在測試之後要做哪些事情? 由於 after
比較少使用我們就先以 before
為主,我們先看以下超簡單的範例
# user.rb
def change_name(new_name)
return false if new_name.blank?
self.name = new_name
save!
end
end
#user_spec.rb
describe '#change_name' do
it 'will change the name' do
@user = User.create!(name: 'test')
@user.change_name('new_name')
expect(@user.name).to eq('new_name')
end
it 'will not change name' do
@user = User.create!(name: 'test')
@user.change_name('')
expect(@user.change_name('')).to eq(false)
end
end
如果用 before
修改可以寫成以下,預設為before(:each)
。
#user_spec.rb
describe '#change_name' do
before do
p '這是before'
@user = User.create!(name: 'test')
end
it 'will change the name' do
@user.change_name('new_name')
expect(@user.name).to eq('new_name')
end
it 'return false if name is blank' do
expect(@user.change_name('')).to eq(false)
end
end
這麼做的好處就是可以將一些 it
會重複使用到的 code 放到 before 裡節省 code
但仔細看會發現如果是使用 before(:each)
的話在執行兩個 it
前會進去 before
$ rspec spec/models/user_spec.rb
.."這是before"
."這是before"
.
Finished in 0.13856 seconds (files took 3.94 seconds to load)
4 examples, 0 failures
如果是before(:all)
呢?
rspec spec/models/user_spec.rb
.."這是before"
..
Finished in 0.11651 seconds (files took 3.64 seconds to load)
4 examples, 0 failures
只會進去一次!所以說
before(:each)
=> 在每個 it
之前執行beofore(:all)
=> 在每個 describe
之前執行beofore(:suite)
=> 在每個測試檔之前執行(很少用到就不舉例了)
有更多 before
用法可以在 before-and-after-hooks 查到
想知道每個 before
先後排序可以看這篇
in-rspec-whats-the-difference-between-beforesuite-and-beforeal
after
個人最常用來在解除 TimeCop.freeze()
,有些測試會去針對時程上或是訊息含有時間時就會推薦先將測試前指定時間點並在after
復原。這樣一來整個區間內都會在 Timecop 指定的時間中。
RSpec.describe User, type: :model do
before(:all) do
Timecop.freeze(Time.current)
end
after(:all) do
Timecop.return
end
describe '#change_name' do
before do
p '這是before'
@user = User.create!(name: 'test')
end
it 'will change the name' do
@user.change_name('new_name')
expect(@user.name).to eq('new_name')
end
it 'return false if name is blank' do
expect(@user.change_name('')).to eq(false)
end
end
end
因為有一些
明天就可以來說明 let
、let!
、subject
摟!