Rspec and Rails
Upcoming SlideShare
Loading in...5
×
 

Rspec and Rails

on

  • 1,839 views

This is a presentation which shows how to unit test with rspec, factory girl in a rails project

This is a presentation which shows how to unit test with rspec, factory girl in a rails project

Statistics

Views

Total Views
1,839
Views on SlideShare
1,445
Embed Views
394

Actions

Likes
6
Downloads
66
Comments
0

2 Embeds 394

http://dev.afterclassroom.com 346
http://localhost 48

Accessibility

Categories

Upload Details

Uploaded via as Apple Keynote

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n

Rspec and Rails Rspec and Rails Presentation Transcript

  • Rspec and Rails Abraham Kuri
  • Table of Contents01 Rails setup02 Expectations & Matchers03 Shoulda & DRY Specs04 Context & Describe blocks05 Before block06 Stub & Mock07 Where to go next?
  • Rails Setup
  • Rails Setup
  • Rails Setup$ rails new <app_name> --skip-test-unit
  • Rails Setup$ rails new <app_name> --skip-test-unitGemfile:group :test, :development do gem rspec-rails gem "factory_girl_rails" gem ffakerend
  • Rails Setup$ rails new <app_name> --skip-test-unitGemfile:group :test, :development do gem rspec-rails gem "factory_girl_rails" gem ffakerend
  • Rails Setup$ rails new <app_name> --skip-test-unitGemfile:group :test, :development do gem rspec-rails gem "factory_girl_rails" gem ffakerend
  • Rails Setup$ rails new <app_name> --skip-test-unitGemfile:group :test, :development do gem rspec-rails gem "factory_girl_rails" gem ffakerend$ bundle install
  • Rails Setup$ rails new <app_name> --skip-test-unitGemfile:group :test, :development do gem rspec-rails gem "factory_girl_rails" gem ffakerend$ bundle install$ rails g rspec:install
  • Expectations & Matchers‣ user_spec.rb
  • Expectations & Matchers‣ user_spec.rb
  • Expectations & Matchers‣ user_spec.rbdescribe User do let(:user) { FactoryGirl.create(:user) } subject { user } it should not be valid without a name do user.name = nil user.should_not == nil endend
  • Expectations & Matchers‣ user_spec.rbdescribe User do let(:user) { FactoryGirl.create(:user) } subject { user } it should not be valid without a name do user.name = nil user.should_not == nil endend
  • Expectations & Matchers‣ user_spec.rbdescribe User do let(:user) { FactoryGirl.create(:user) } subject { user } it should not be valid without a name do user.name = nil modifier user.should_not == nil endend
  • Expectations & Matchers‣ user_spec.rbdescribe User do let(:user) { FactoryGirl.create(:user) } subject { user } it should not be valid without a name do user.name = nil modifier user.should_not == nil endend
  • Expectations & Matchers‣ user_spec.rbdescribe User do let(:user) { FactoryGirl.create(:user) } subject { user } it should not be valid without a name do user.name = nil modifier user.should_not == nil endend matcher
  • Expectations & Matchers‣ user_spec.rbdescribe User do let(:user) { FactoryGirl.create(:user) } subject { user } it should not be valid without a name do user.name = nil modifier user.should_not == nil endend matcher
  • Expectations & Matchers‣ user_spec.rbdescribe User do let(:user) { FactoryGirl.create(:user) } subject { user } it should not be valid without a name do user.name = nil modifier user.should_not == nil endend matcher
  • Expectations & Matchers‣ user_spec.rbdescribe User do let(:user) { FactoryGirl.create(:user) } subject { user } it should not be valid without a name do user.name = nil modifier user.should_not == nil endend matcher
  • Expectations & Matchers‣ user_spec.rbdescribe User do let(:user) { FactoryGirl.create(:user) } subject { user } it should not be valid without a name do user.name = nil modifier user.should_not == nil endend matcher describe User do let(:user) { FactoryGirl.create(:user) } subject { user } its(:name) { should_not be_nil } end
  • Expectations & Matchers‣ user_spec.rbdescribe User do let(:user) { FactoryGirl.create(:user) } subject { user } it should not be valid without a name do user.name = nil modifier user.should_not == nil endend matcher describe User do let(:user) { FactoryGirl.create(:user) } subject { user } its(:name) { should_not be_nil } end
  • Other matchers
  • Other matchersuser.name.should == "Abraham"user.friends.should > 3user.alive.should == trueuser.alive.should_not == falseuser.girlfriend.should == niluser.should be_alive have(n)user.friends.should include(other_user) have_at_least(n) have_at_most(n)user.should have(2).arms
  • Other matchersuser.name.should == "Abraham"user.friends.should > 3user.alive.should == true user.alive.should be_trueuser.alive.should_not == falseuser.girlfriend.should == niluser.should be_alive have(n)user.friends.should include(other_user) have_at_least(n) have_at_most(n)user.should have(2).arms
  • Other matchersuser.name.should == "Abraham"user.friends.should > 3user.alive.should == true user.alive.should be_trueuser.alive.should_not == false user.alive.should_not be_falseuser.girlfriend.should == niluser.should be_alive have(n)user.friends.should include(other_user) have_at_least(n) have_at_most(n)user.should have(2).arms
  • Other matchersuser.name.should == "Abraham"user.friends.should > 3user.alive.should == true user.alive.should be_trueuser.alive.should_not == false user.alive.should_not be_falseuser.girlfriend.should == nil user.alive.should be_niluser.should be_alive have(n)user.friends.should include(other_user) have_at_least(n) have_at_most(n)user.should have(2).arms
  • Shoulda to the rescue
  • Shoulda to the rescue
  • Shoulda to the rescuedescribe User do let(:user) { FactoryGirl.create(:user) } subject { user } its(:name) { should_not be_nil }end
  • Shoulda to the rescuedescribe User do let(:user) { FactoryGirl.create(:user) } subject { user } its(:name) { should_not be_nil }end
  • Shoulda to the rescuedescribe User do let(:user) { FactoryGirl.create(:user) } subject { user } its(:name) { should_not be_nil }endit { should validate_presence_of(:name) }
  • Shoulda to the rescuedescribe User do let(:user) { FactoryGirl.create(:user) } subject { user } its(:name) { should_not be_nil }endit { should validate_presence_of(:name) }it { should validate_uniqueness_of(:email) }it { should have_many(:friends).through(:friendship) }
  • Shoulda to the rescuedescribe User do let(:user) { FactoryGirl.create(:user) } subject { user } its(:name) { should_not be_nil }endit { should validate_presence_of(:name) }it { should validate_uniqueness_of(:email) }it { should have_many(:friends).through(:friendship) }it { should belong_to(:user)}
  • Context & Describe Blocks
  • Context & Describe Blocksdescribe User do describe when sleep do it snores describe with a soft pillow do it still snores it have good dreams end endend
  • Context & Describe Blocksdescribe User do describe when sleep do it snores describe with a soft pillow do it still snores it have good dreams end endend
  • Context & Describe Blocksdescribe User do describe when sleep do it snores describe with a soft pillow do it still snores it have good dreams end endend Use context instead of describe
  • Context & Describe Blocksdescribe User do describe when sleep do it snores describe with a soft pillow do it still snores it have good dreams end endend Use context instead of describedescribe User do context when sleep do it snores context with a soft pillow do it still snores it have good dreams end endend
  • Context & Describe Blocksdescribe User do describe when sleep do it snores describe with a soft pillow do it still snores it have good dreams end endend Use context instead of describedescribe User do context when sleep do it snores context with a soft pillow do it still snores it have good dreams end endend
  • Before block
  • Before blockdescribe friends names do context when has friends do it should have 3 friends do 3.times { user.friends << FactoryGirl.create(:friend) } user.should have(3).friends end it should return friend names do 3.times { user.friends << FactoryGirl.create(:friend) } user.friend_names.should == user.friends.map(&:name) end endend
  • Before blockdescribe friends names do context when has friends do it should have 3 friends do 3.times { user.friends << FactoryGirl.create(:friend) } user.should have(3).friends end it should return friend names do 3.times { user.friends << FactoryGirl.create(:friend) } user.friend_names.should == user.friends.map(&:name) end endend
  • Before blockdescribe friends names do context when has friends do it should have 3 friends do 3.times { user.friends << FactoryGirl.create(:friend) } user.should have(3).friends end it should return friend names do 3.times { user.friends << FactoryGirl.create(:friend) } user.friend_names.should == user.friends.map(&:name) end endend Let’s be more DRY
  • Before blockdescribe friends names do context when has friends do it should have 3 friends do 3.times { user.friends << FactoryGirl.create(:friend) } user.should have(3).friends end it should return friend names do 3.times { user.friends << FactoryGirl.create(:friend) } user.friend_names.should == user.friends.map(&:name) end endend Let’s be more DRYdescribe friends names do
  • Before blockdescribe friends names do context when has friends do it should have 3 friends do 3.times { user.friends << FactoryGirl.create(:friend) } user.should have(3).friends end it should return friend names do 3.times { user.friends << FactoryGirl.create(:friend) } user.friend_names.should == user.friends.map(&:name) end endend Let’s be more DRYdescribe friends names do context when has friends do
  • Before blockdescribe friends names do context when has friends do it should have 3 friends do 3.times { user.friends << FactoryGirl.create(:friend) } user.should have(3).friends end it should return friend names do 3.times { user.friends << FactoryGirl.create(:friend) } user.friend_names.should == user.friends.map(&:name) end endend Let’s be more DRYdescribe friends names do context when has friends do before do
  • Before blockdescribe friends names do context when has friends do it should have 3 friends do 3.times { user.friends << FactoryGirl.create(:friend) } user.should have(3).friends end it should return friend names do 3.times { user.friends << FactoryGirl.create(:friend) } user.friend_names.should == user.friends.map(&:name) end endend Let’s be more DRYdescribe friends names do context when has friends do before do 3.times { user.friends << FactoryGirl.create(:friend) }
  • Before blockdescribe friends names do context when has friends do it should have 3 friends do 3.times { user.friends << FactoryGirl.create(:friend) } user.should have(3).friends end it should return friend names do 3.times { user.friends << FactoryGirl.create(:friend) } user.friend_names.should == user.friends.map(&:name) end endend Let’s be more DRYdescribe friends names do context when has friends do before do 3.times { user.friends << FactoryGirl.create(:friend) } end
  • Before blockdescribe friends names do context when has friends do it should have 3 friends do 3.times { user.friends << FactoryGirl.create(:friend) } user.should have(3).friends end it should return friend names do 3.times { user.friends << FactoryGirl.create(:friend) } user.friend_names.should == user.friends.map(&:name) end endend Let’s be more DRYdescribe friends names do context when has friends do before do 3.times { user.friends << FactoryGirl.create(:friend) } end it { should have(3).friends }
  • Before blockdescribe friends names do context when has friends do it should have 3 friends do 3.times { user.friends << FactoryGirl.create(:friend) } user.should have(3).friends end it should return friend names do 3.times { user.friends << FactoryGirl.create(:friend) } user.friend_names.should == user.friends.map(&:name) end endend Let’s be more DRYdescribe friends names do context when has friends do before do 3.times { user.friends << FactoryGirl.create(:friend) } end it { should have(3).friends } its(:friend_names) { should == user.friends.map(&:name) }
  • Before blockdescribe friends names do context when has friends do it should have 3 friends do 3.times { user.friends << FactoryGirl.create(:friend) } user.should have(3).friends end it should return friend names do 3.times { user.friends << FactoryGirl.create(:friend) } user.friend_names.should == user.friends.map(&:name) end endend Let’s be more DRYdescribe friends names do context when has friends do before do 3.times { user.friends << FactoryGirl.create(:friend) } end it { should have(3).friends } its(:friend_names) { should == user.friends.map(&:name) } end
  • Before blockdescribe friends names do context when has friends do it should have 3 friends do 3.times { user.friends << FactoryGirl.create(:friend) } user.should have(3).friends end it should return friend names do 3.times { user.friends << FactoryGirl.create(:friend) } user.friend_names.should == user.friends.map(&:name) end endend Let’s be more DRYdescribe friends names do context when has friends do before do 3.times { user.friends << FactoryGirl.create(:friend) } end it { should have(3).friends } its(:friend_names) { should == user.friends.map(&:name) } endend
  • Before blockdescribe friends names do context when has friends do it should have 3 friends do 3.times { user.friends << FactoryGirl.create(:friend) } user.should have(3).friends end it should return friend names do 3.times { user.friends << FactoryGirl.create(:friend) } user.friend_names.should == user.friends.map(&:name) end endend Let’s be more DRYdescribe friends names do context when has friends do before do 3.times { user.friends << FactoryGirl.create(:friend) } end it { should have(3).friends } its(:friend_names) { should == user.friends.map(&:name) } endend
  • Before blockdescribe friends names do context when has friends do it should have 3 friends do 3.times { user.friends << FactoryGirl.create(:friend) } user.should have(3).friends end it should return friend names do 3.times { user.friends << FactoryGirl.create(:friend) } user.friend_names.should == user.friends.map(&:name) end endend Let’s be more DRYdescribe friends names do context when has friends do before do 3.times { user.friends << FactoryGirl.create(:friend) } end it { should have(3).friends } its(:friend_names) { should == user.friends.map(&:name) } endend Much better
  • Stubs & Mocking
  • Stubs & Mocking‣ Stubs For replacing a method with code that return a specified result
  • Stubs & Mocking‣ Stubs For replacing a method with code that return a specified result‣ Mocks A stub with an expectations that the method gets called
  • Stub it out
  • Stub it outapp/models/user.rbclass User < ActiveRecord::Base has_one :stomach def feed_stomach stomach.feed(self) self.status = "full" endend
  • Stub it out User feed_stomachapp/models/user.rbclass User < ActiveRecord::Base has_one :stomach def feed_stomach stomach.feed(self) self.status = "full" endend
  • Stub it out User feed_stomachapp/models/user.rbclass User < ActiveRecord::Base has_one :stomach def feed_stomach stomach.feed(self) self.status = "full" endend
  • Stub it out User Stomach feed_stomach def feed(*args) return nil endapp/models/user.rbclass User < ActiveRecord::Base has_one :stomach def feed_stomach stomach.feed(self) self.status = "full" endend
  • Stub it out User Stomach feed_stomach def feed(*args) return nil end user.stomach.stub(:feed_stomach)app/models/user.rbclass User < ActiveRecord::Base has_one :stomach def feed_stomach stomach.feed(self) self.status = "full" endend
  • Complete spec
  • Complete spec def feed_stomach stomach.feed(self) self.status = "full" end
  • Complete spec def feed_stomach stomach.feed(self)/spec/models/user_spec.rb self.status = "full" end We need to test that feed is called
  • Complete spec def feed_stomach stomach.feed(self)/spec/models/user_spec.rb self.status = "full" enddescribe User do We need to test that feed is called
  • Complete spec def feed_stomach stomach.feed(self)/spec/models/user_spec.rb self.status = "full" enddescribe User do let(:user) { FactoryGirl.create(:user) } We need to test that feed is called
  • Complete spec def feed_stomach stomach.feed(self)/spec/models/user_spec.rb self.status = "full" enddescribe User do let(:user) { FactoryGirl.create(:user) } We need to test that feed is called
  • Complete spec def feed_stomach stomach.feed(self)/spec/models/user_spec.rb self.status = "full" enddescribe User do let(:user) { FactoryGirl.create(:user) } describe #feed_stomach do We need to test that feed is called
  • Complete spec def feed_stomach stomach.feed(self)/spec/models/user_spec.rb self.status = "full" enddescribe User do let(:user) { FactoryGirl.create(:user) } describe #feed_stomach do it set the status to full do We need to test that feed is called
  • Complete spec def feed_stomach stomach.feed(self)/spec/models/user_spec.rb self.status = "full" enddescribe User do let(:user) { FactoryGirl.create(:user) } describe #feed_stomach do it set the status to full do user.stomach.stub(:feed) We need to test that feed is called
  • Complete spec def feed_stomach stomach.feed(self)/spec/models/user_spec.rb self.status = "full" enddescribe User do let(:user) { FactoryGirl.create(:user) } describe #feed_stomach do it set the status to full do user.stomach.stub(:feed) user.feed_stomach We need to test that feed is called
  • Complete spec def feed_stomach stomach.feed(self)/spec/models/user_spec.rb self.status = "full" enddescribe User do let(:user) { FactoryGirl.create(:user) } describe #feed_stomach do it set the status to full do user.stomach.stub(:feed) user.feed_stomach user.status.should == "full" We need to test that feed is called
  • Complete spec def feed_stomach stomach.feed(self)/spec/models/user_spec.rb self.status = "full" enddescribe User do let(:user) { FactoryGirl.create(:user) } describe #feed_stomach do it set the status to full do user.stomach.stub(:feed) user.feed_stomach user.status.should == "full" end We need to test that feed is called
  • Complete spec def feed_stomach stomach.feed(self)/spec/models/user_spec.rb self.status = "full" enddescribe User do let(:user) { FactoryGirl.create(:user) } describe #feed_stomach do it set the status to full do user.stomach.stub(:feed) user.feed_stomach user.status.should == "full" end end We need to test that feed is called
  • Complete spec def feed_stomach stomach.feed(self)/spec/models/user_spec.rb self.status = "full" enddescribe User do let(:user) { FactoryGirl.create(:user) } describe #feed_stomach do it set the status to full do user.stomach.stub(:feed) user.feed_stomach user.status.should == "full" end endend We need to test that feed is called
  • Mocha flavor
  • Mocha flavor/app/models/user.rbdef fb_friends_ids user = FbGraph::User.me(self.token) user.friends.map { |o| o.raw_attributes[:id] }end
  • Mocha flavor/app/models/user.rb ["1", "45", "987"]def fb_friends_ids user = FbGraph::User.me(self.token) user.friends.map { |o| o.raw_attributes[:id] }end
  • Mocha flavor/app/models/user.rb ["1", "45", "987"]def fb_friends_ids user = FbGraph::User.me(self.token) user.friends.map { |o| o.raw_attributes[:id] }end/app/specs/user_spec.rb
  • Mocha flavor/app/models/user.rb ["1", "45", "987"]def fb_friends_ids user = FbGraph::User.me(self.token) user.friends.map { |o| o.raw_attributes[:id] }end/app/specs/user_spec.rbit calls the Facebook Graph to get friends do FbGraph::User.should_receive(:me).with(user.token) .and_return(["1", "45", "987"]) user.fb_friends_idsend stubs the method + expectation with correct param return value
  • Mocha flavor/app/models/user.rb ["1", "45", "987"]def fb_friends_ids user = FbGraph::User.me(self.token) user.friends.map { |o| o.raw_attributes[:id] }end/app/specs/user_spec.rbit calls the Facebook Graph to get friends do FbGraph::User.should_receive(:me).with(user.token) .and_return(["1", "45", "987"]) user.fb_friends_idsend stubs the method + expectation with correct param return value
  • Where to go next?http://rspec.info/ https://github.com/rspec/rspec https://github.com/thoughtbot/shoulda http://eggsonbread.com/2010/03/28/my-rspec- best-practices-and-tips/ http://www.rubyinside.com/how-to-rails-3-and- rspec-2-4336.html
  • Rspec & Rails Abraham Kuri