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

Rails Testing AntiPatterns

Rails Testing AntiPatterns

Back in 1999, Kent Beck popularized test-first development with his industry changing book eXtreme Programming Explained. Since that time, testing in our applications is not something that would be nice to have, but essential to inspire confidence, catch regressions, and encourage simple designs. However, since tests have become such a large percentage of our applications, they also are prone to code smells and various testing anti patterns.

In his talk, Kevin Faustino will go through various Testing AntiPatterns he has found in Rails projects.

Kevin Faustino

October 23, 2012
Tweet

More Decks by Kevin Faustino

Other Decks in Technology

Transcript

  1. “A pattern that shouldn’t be used because it is known

    to produce less than optimal results.” -Gerard Meszaros
  2. Test Reader is not able to see the cause and

    effect between the fixture and the verification logic
  3. Rails Fixtures describe Order do it 'sets purchase price' do

    order = Order.last # Where did we even set this ? order.purchase_price.should eq("9.99") # ???? end end
  4. Local describe User do let(:first_name) { 'Bruce' } let(:last_name) {

    'Wayne' } subject { FactoryGirl.build(:user, first_name: first_name, last_name: last_name) } its(:full_name) { should eq("#{first_name} + #{last_name}") } end
  5. Valid Factory FactoryGirl.define do factory :user do email first_name {

    Faker::Name.first_name } last_name { Faker::Name.last_name } password "password1" end end
  6. Test Your Factories! FactoryGirl.factories.map(&:name).each do |factory_name| describe "The #{factory_name} factory"

    do it 'is valid' do build(factory_name).should be_valid end end end -http://robots.thoughtbot.com/post/30994874643/testing-your-factories-first
  7. Set belong_to relationships FactoryGirl.define do factory :standing do season #

    Season Factory team # Team Factory season_type 'regular' end end
  8. timecop (Time) new_time = Time. local(2008, 9, 1, 12, 0,

    0) Timecop.freeze(new_time) sleep(10) new_time == Time.now # ==> true
  9. describe "#to_rss" do let(:url) { 'http://adventuresincoding.com' } subject { Nokogiri::XML(blog.to_rss)

    } def text_at(*args) args.inject(subject) { |s,r| s.send(:at, r) }.inner_text end it "must be RSS version 2.0" do subject.at('rss')['version'].should == '2.0' end it "has a title" do text_at('rss', 'title').should eq(subject.title) end it "has a link to the blog" do text_at('rss','link').should eq(url) end end
  10. Old Cukes Feature: Signing In Background: Given I am not

    authenticated Scenario: Successful Login Given 1 user And I go to the sign in page When I fill in "Email" with "[email protected]" And I fill in "Password" with "batman" And I press "Sign in" Then I should be on the dashboard page And I should see "Signed in successfully."
  11. Avoid Incidental Details Scenario: Successful Login Given a user exists

    When I sign in Then I should be shown the dashboard
  12. Use Declarative Style Scenario: Redirect user to originally requested page

    after logging in Given I am an unauthenticated User When I attempt to view some restricted content Then I am shown a login form When I authenticate with valid credentials Then I should be shown the restricted content Example Source: The Cucumber Book
  13. A controller is a class with methods It should have

    tests! http://solnic.eu/2012/02/02/yes-you-should-write-controller-tests.html
  14. describe('User', function(){ describe('#save()', function(){ it('should save without error', function(done){ var

    user = new User('Luna'); user.save(function(err){ if (err) throw err; done(); }); }) }) })
  15. Stub Ajax calls to Rails! var server = sinon.fakeServer.create(); ...

    server.requests[0].respond( 200, { "Content-Type": "application/json" }, JSON.stringify([{ id: 1, text: "Sinon rules!" }]) );