Kinh nghiệm sử dụng Rspec
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. 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 { ...
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.
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
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
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.
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.