Tips to make your rspec specs awesome
-
Upload
swati-jadhav -
Category
Engineering
-
view
101 -
download
5
Transcript of Tips to make your rspec specs awesome
Tips To Make Your RSpec Specs Awesome
describe FindReaction do#Spec 1 it "should return no reaction template when there are no reaction templates" do post = create :post, locale: "en", type: "basic" reaction = FindReaction.for(post).reaction expect(reaction.blank?).to be_trueend #Spec 2 it "should return no reaction template if reaction templates exist, but non fitting" do post = create :post, locale: "en", type: "basic" reaction1 = ReactionTemplate.create locale: "de", subtypes: ["basic", "top_x"] reaction2 = ReactionTemplate.create locale: "en", subtypes: ["slideshow", "top_x"] reaction = FindReaction.for(post).reaction expect(reaction.blank?).to be_true end
#Spec 3 it "should return the right reaction if it exists" do post = create :post, locale: "en", type: "basic" reaction1 = ReactionTemplate.create locale: "en", subtypes: ["basic", "top_x"] reaction2 = ReactionTemplate.create locale: "en", subtypes: ["basic", "top_x"] reaction3 = ReactionTemplate.create locale: "en" , subtypes: ["slideshow", "top_x"] reaction = FindReaction.for(post).reaction expect(reaction.blank?).to be_true expect(reaction).to eq reaction2end #Spec 4 it "should change posts reaction_template when attaching it" do post = create :post, locale: "en", type: "basic" expect(post.reaction_template.nil?).to be_true reaction = ReactionTemplate.create locale: "en", subtypes: ["basic", "top_x"] FindReaction.for(post).attach expect(post.reaction_template.nil?).to be_false expect(post.reaction_template).to eq reaction endend
Keep your specs DRY – use before blocks
Use before :all instead of before :each when possible
Use conditional hooks• Sometimes if you want to execute some piece of code only
for one example but not for all examples in a context then you can use conditional hooks.
context "#update" do before(:each, run: true) do # do something end it "example1", run: :true it "example2"end
• Now before(:each) will run only for first example but not for second example.
Use build instead of create when possible
Use describe to create nested specs groups. describe should
relate to an operation or an object
Use variables instead of constants to keep your specs from becoming
too fragile.
Use RSpec’s magnificent be_ syntactic sugar
RSpec has many syntactic sugars that makes your specs more readable.
for example:expect(reaction.blank?).to be_trueWhen an object reacts to some_method_name? RSpec allows you to write the test in the following way:object.should be_some_method_nameOr in our case:
expect(reaction).to be_blank
Use create! and save! instead of create and save
If/When rule of thumb
Use subject/it clauses to keep your specs DRY’er and cleaner
result: FindReaction.for(@post).reactionThis can be easily extracted into
subject {FindReaction.for(@post).reaction}
One assertion per test case
• This way if the spec fails, you immediately know what went wrong and don’t even have to look at the detailed output of the failure. It also keeps your specs clean and focused on what they’re supposed to test
Use RSpec’s expect {} block to describe a change in the state of an
object
RSpec has a nice and clean way to describe these kind of state changes:expect { some_operation }.to change{something}.from(initial_value).to(final_value)It is much cleaner and more readable this way.
Use shared examples.• When you want to test the same functionality across different subjects, for example different kinds
of users, use shared examples.context "#edit" do it "admin should be able to edit his profile" it "distributor should be able to edit his profile"End
You can write as
context "#edit" do shared_examples "profile_editing" do it "user should be able to edit his profile" end context "admin" do include_examples "profile_editing" it "should be able see to list of distributors" end context "distributor" do include_examples "profile_editing" it "should not able to see list of distributors" endEnd
Note - A word of caution – you may lost readability if you use too many shared examples in single file
Use correct expectations for a spec
Use the new syntax for object creation
• Use the new FactoryGirl syntax that is supported in factory_girl4. This helps the code be clean
create(:user)
instead of FactoryGirl.create(:user)
Use expect and not should syntax
• It’s just nice and clean! expect(User.all.count).to eq(1)
instead ofUser.all.count.should == 1
Note :- Use the Transpec gem helps you to convert from should syntax to expect syntax
Tagging
# spec/models/commission_spec.rb
describe Commission, commission: true do
# do something
End
rspec –tag commission
Note: We can tag entire context or a single example in the spec file
describe FindReaction do
before :all do
@post = build :post, locale: "en", type: "basic"
end
before :each do
@post.reaction = nil
end
describe :reaction do
subject { FindReaction.for(@post).reaction }
#Spec 1
context "there are no reaction templates" do
it {expect(subject).to be_blank }
end
#Spec 2
context "reaction templates exist, but non fitting" do
before :each do
reaction1 = ReactionTemplate.create! locale: "de", subtypes: ["basic", "top_x"]
reaction2 = ReactionTemplate.create! locale: "en", subtypes: ["slideshow", "top_x"]
end
it {expect(subject).to be_blank }
end
#Spec 3
context "fitting reaction templates exist" do
before :each do
@reaction1 = ReactionTemplate.create! locale: @post.locale, subtypes: [@post.type, "top_x"]
@reaction2 = ReactionTemplate.create! locale: @post.locale, subtypes: [@post.type, "top_x"]
@reaction3 = ReactionTemplate.create! locale: @post.locale, subtypes: ["slideshow", "top_x"]
end
it {expect(subject).not_to be_blank}
it {expect(subject).to eq @reaction2}
end
end
describe :attach do
#Spec 4
context "attaching a reaction to post" do
before :each do
@reaction = ReactionTemplate.create! locale: @post.locale, subtypes: [@post.type, "top_x"]
end
it "should change posts reaction template" do
expect {
FindReaction.for(@post).attach
}.to change{@post.reaction_template}.from(nil).to(@reaction)
end
end
end
end
CONCLUSION
• Our test-suite runs faster• Our test file is more readable• The failure output provided by RSpec is better• We’re not repeating ourselves between specs• It is extremely easy to extend the specs to
describe new features
Thank you