TDD/BDD Tools and Practice in Rails

Created by Tasha Jones / @latazzajones

Contents

  1. Why TDD/BDD?
  2. Overview of the tools
    • Get to know the docs
  3. Putting the tools to use

Why TDD/BDD?

  • Tests help you plan the feature
  • Tests show you that your feature works how you expect
  • Tests allow future devs to change your code safely
  • Tests document the intended functionality of the feature

Overview of the Tools

  1. RSpec
  2. Capybara
  3. FactoryGirl

RSpec

RSpec is a Behaviour-Driven Development tool for Ruby programmers.

Check out the docs!
http://www.relishapp.com/rspec/rspec-rails/v/3-4/docs/

Capybara

Capybara is a library that helps you write more human readable tests.

Check out the docs!
https://github.com/jnicklas/capybara http://www.rubydoc.info/github/jnicklas/capybara

FactoryGirl

Is a tool maintained by Thoughtbot and used to create data objects(aka: fixtures) for tests

Check out the docs!
https://github.com/thoughtbot/factory_girl/wiki

Let's Build Something!

We're going to add a '#new' action to a controller in my Garbage Pail Kids app.

Let's See Some TDD!

I'd like to be able to grow my collection of Garbage Pail Kids. Lets add a #new action.

Spec as documentation!

aka - spec in real life

All specs are tools for understanding features better (even missing specs)

  • Sometimes there's beautiful spec
    • read the spec
  • Sometimes there's no spec
    • add the spec
  • Sometimes there's old spec
    • refactor the spec

let(:statements)   { create amazing_things }

let!(:statements)   { create amazing_things }

Keeping it in context

  • Describe
  • Context
  • It

RSpec Expectations

aka - please stop using should!

  • Should was depricated in 2012
  • Myron say's it better (-Myron Marston RSpec's New Expectation Syntax)
    • "RSpec's should syntax, as elegantly as it reads,
      is prone to producing weird, confusing failures when testing delegate/proxy objects"
    • "The problem is that rspec-expectations defines should on Kernel,
      and BasicObject does not include Kernel"

Keeping it in context

Context implies a change in the conditions around the code running

Hai-please! One assertion per test!

  • Easier to debug
  • You can be confident you're testing what you say you're testing

Side note about the where method

don't chain it.

Person.where(:first_name => "Monique").where(:last_name => "Meloche").where(:import_id => import.id).first

can just be

Person.where(first_name: "Monique", last_name: "Meloche", import_id: import.id).first

What I learned about this feature based on reading through and reworking the spec

We're either testing or managing WAY too much in one model (tbd)

    
    it "should create an order for everything, too" do
    	import.orders.sort_by {|o| o.id}.each_with_index do |order, index|
    		order.organization.should eq import.organization
    		order.transaction_id.should be_nil
    		order.details.should_not be_nil
    		order.import.should eq import
    		order.payment_method.should   eq target_orders[index].payment_method
    		order.person.should           eq target_orders[index].person
    	end
    end
    
    it "should create settled items" do
    	import.orders.each do |order|
    		order.items.each {|item| item.should be_settled}
    	end
    end
    			

We're not testing the unhappy path

What happens when an import fails?