Upgrade to Pro — share decks privately, control downloads, hide ads and more …

4 Steps to Faster Rails Tests

4 Steps to Faster Rails Tests

This talk was presented at Magrails on October 14th 2011. Check magrails.com for the video, and github.com/seenmyfate for sample code

Tom Clements

October 14, 2011
Tweet

More Decks by Tom Clements

Other Decks in Programming

Transcript

  1. 4 Steps to Faster Rails Test Tom Clements Senior Developer,

    On The Beach tom-clements.com | github.com/seenmyfate @Seenmyfate
  2. Let's look at some numbers $ time rake spec 31.486

    seconds $ time bundle exec rspec spec 15.741 seconds $ time rspec spec 14.932 seconds
  3. 0.186 seconds # spec/some_spec.rb # require 'spec_helper' describe "Nothing" do

    # nada end 0 examples, 0 failures 0.186 seconds total
  4. For our unit tests - Why are we loading the

    entire rails environment? Because our business logic is in our active record models And we need rails to run tests against classes that inherit from ActiveRecord::Base Because we're breaking SRP
  5. 4 Steps Extract business logic into modules Extract domain objects

    into classes Mixin and delegate Test in isolation
  6. An example require 'spec_helper' describe Basket do context "total_discount" do

    let(:basket) { Basket.create! } let(:basket_items) { [BasketItem.create!(:discount => 10), BasketItem.create!(:discount => 20) ]} it "should return the total discount" do basket = Basket.create! basket.basket_items = basket_items basket.total_discount.should == 30 end end end
  7. 7.092 seconds to run time rspec spec . Finished in

    0.24435 seconds 1 example, 0 failures rspec spec 7.092 total
  8. And the test require 'discount_calculator' class FakeBasket include DiscountCalculator end

    describe DiscountCalculator do context "#total_discount" do it "should return the total discount" do basket = FakeBasket.new basket_items = [stub(:discount => 10), stub(:discount => 20)] basket.stub(:basket_items) { basket_items } basket.total_discount.should eq 30 end end end
  9. 0.350 seconds to run time rspec spec . Finished in

    0.00121 seconds 1 example, 0 failures rspec spec 0.350 total
  10. And delegate class Basket < ActiveRecord::Base has_many :basket_items def total_discount

    DiscountCalculator.new. total_discount(basket_items) end end
  11. And the test require 'discount_calculator' describe DiscountCalculator do context "#total_discount"

    do let(:items) { [stub(:discount => 10), stub(:discount => 20)] } it "should return the total discount" do calculator = DiscountCalculator.new calculator.total_discount(items).should eq 30 end end end
  12. 0.342 seconds to run time rspec spec . Finished in

    0.00101 seconds 1 example, 0 failures rspec spec 0.342 total
  13. 4 Steps to Faster Rails Test Tom Clements Senior Developer,

    On The Beach tom-clements.com | github.com/seenmyfate @Seenmyfate