Tips to make your rspec specs awesome

25
Tips To Make Your RSpec Specs Awesome

Transcript of Tips to make your rspec specs awesome

Page 1: Tips to make your rspec specs awesome

Tips To Make Your RSpec Specs Awesome

Page 2: 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

Page 3: Tips to make your rspec specs awesome

#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

Page 4: Tips to make your rspec specs awesome

Keep your specs DRY – use before blocks

Page 5: Tips to make your rspec specs awesome

Use before :all instead of before :each when possible

Page 6: Tips to make your rspec specs awesome

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.

Page 7: Tips to make your rspec specs awesome

Use build instead of create when possible

Page 8: Tips to make your rspec specs awesome

Use describe to create nested specs groups. describe should

relate to an operation or an object

Page 9: Tips to make your rspec specs awesome

Use variables instead of constants to keep your specs from becoming

too fragile.

Page 10: Tips to make your rspec specs awesome

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

Page 11: Tips to make your rspec specs awesome

Use create! and save! instead of create and save

Page 12: Tips to make your rspec specs awesome

If/When rule of thumb

Page 13: Tips to make your rspec specs awesome

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}

Page 14: Tips to make your rspec specs awesome

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

Page 15: Tips to make your rspec specs awesome

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.

Page 16: Tips to make your rspec specs awesome

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

Page 17: Tips to make your rspec specs awesome

Use correct expectations for a spec

Page 18: Tips to make your rspec specs awesome

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)

Page 19: Tips to make your rspec specs awesome

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

Page 20: Tips to make your rspec specs awesome

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

Page 21: Tips to make your rspec specs awesome

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

Page 22: Tips to make your rspec specs awesome

#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

Page 23: Tips to make your rspec specs awesome

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

Page 24: Tips to make your rspec specs awesome

Thank you

Page 25: Tips to make your rspec specs awesome