Kinh nghiệm sử dụng Rspec
Bài đăng này đã không được cập nhật trong 7 năm
Xin chào mọi người, hôm nay mình xin viết một số kinh nghiệm của mình khi sử dụng Rspec.
I. Sử dụng Subject
Thứ nhất, khi test nhiều trường hợp với 1 đối tượng giống nhau thì nên sử dụng subject {}
ví dụ:
BAD
it { expect(assigns('message')).to match /it was born in Belville/ }
GOOD
subject { assigns('message') }
it { is_expected.to match /it was born in Billville/ }
Rspec cũng có khả năng định nghĩa 1 object
subject(:hero) { Hero.first }
it "carries a sword" do
expect(hero.equipment).to include "sword"
end
II. Sử dụng let
Khi bạn phải định nghĩa object để sử dụng trong các test của mình, thay vì sử dụng các khối before
thì bạn nên sử dụng let
hay let!
, đây là cách để bạn sử dụng các object mình 1 cách lazy load
. Nghĩa là sẽ chỉ được định nghĩa khi chúng được gọi tới lần đầu tiên và sẽ được cached lại để sử dụng tiếp cho đến khi test chạy xong.
BAD
describe '#type_id' do
before { @resource = FactoryGirl.create :device }
before { @type = Type.find @resource.type_id }
it 'sets the type_id field' do
expect(@resource.type_id).to equal(@type.id)
end
end
GOOD
describe '#type_id' do
let(:resource) { FactoryGirl.create :device }
let(:type) { Type.find resource.type_id }
it 'sets the type_id field' do
expect(resource.type_id).to equal(type.id)
end
end
Hay sử dụng let
để khởi tạo các object và chỉ sử dụng khi cần nhé
GOOD
context 'when updates a not existing property value' do
let(:properties) { { id: Settings.resource_id, value: 'on'} }
def update
resource.properties = properties
end
it 'raises a not found error' do
expect { update }.to raise_error Mongoid::Errors::DocumentNotFound
end
end
III. Nên sử dụng Factory thay vì Fixture
Chủ đề này đã được đề cập đến khá nhiều rồi nhưng mình vẫn muốn nhắc lại vì vẫn thấy mọi ngươi sử dụng fixture hay thậm chí còn tạo object trong spec như thế này:
before {@user = User.new}
BAD
user = User.create(
name: 'Genoveffa',
surname: 'Piccolina',
city: 'Billyville',
birth: '17 Agoust 1982',
active: true
)
GOOD
user = FactoryGirl.create :user
Cách này rất tiện lợi, giúp cho code spec của bạn gọn hơn và bạn cũng dễ dàng tạo ra các object phục vụ việc test. Mà không phải nghĩ nhiều đến chuyện attribute này mình nên đặt là gì, vì bạn sẽ định nghĩa trước ở trong các file ở /spec/factories
.
IV. Không sử dụng should
should
là cú pháp cũ và bây giờ không còn được sử dụng rộng rãi nữa, tuy nhiên khi các bạn tim kiếm về rspec thì vẫn còn gặp khá nhiều example hay tuts viết theo cú pháp này. Các bạn nên sử dụng cú pháp mới là expect
. Để ngăn việc should
vẫn hợp lệ khi chạy test bạn có thể dùng các gem như should_not
hay the should_clean
gem
BAD
it 'should not change timings' do
consumption.occur_at.should == valid.occur_at
end
GOOD
it 'does not change timings' do
expect(consumption.occur_at).to equal(valid.occur_at)
end
Ngoài ra, mình thấy nhiều bạn sử dụng context
và describe
khá loạn và lúng túng khi dùng 2 từ khá này trong rspec. Theo mình thì dù là context
hay describe
thì cũng chỉ là để gom những test chung lại. Tuy nhiên, theo mình hiểu thì describe
là để gói vấn đề, ví dụ:
describe "#validation"
...
end
là để gói các test về validation, và context
sẽ gói ở phạm vi nhỏ hơn và nên ở bên trong describe
. Ví dụ:
describe "#validation"
context "when password is nil" do
it {is_expected.not_to be_valid}
end
end
Với những điều mình chia sẻ ở trên, mong là có thể giúp cho những bạn mới tìm hiểu về Rspec có thể viết spec tốt hơn. Cám ơn các bạn đã đọc bài của mình.
All rights reserved