SuperPumpup (dot com)
General awesomeness may be found here.

06 February 2013

Interface Testing With RSpec

I figured out how to do a pretty cool "interface test" (like described in Chapter 9 of POODR) in RSpec.

In this app I have a polymorphic association from a PurchaseOrder to one of many PurchaseOrderProperties (I know, the names are kind of awful, but that's what they are for now). Simple to set up, but how do I test the interfaces in RSpec? In MiniTest Sandi Metz made it look SO EASY AND AWESOME to just include a module of tests.

Well, I searched around a bit, and this is what I came up with:

/spec/po_propertyable.rb

shared_examples_for "PoPropertyable" do
  describe "implements po_propertyable" do
    let(:properties) { described_class.new() }
    it "reports a price" do
      properties.should respond_to(:price)
    end
  end
end

/spec/models/product_po_properties_spec.rb

require 'spec_helper'
require 'po_propertyable'

describe ProductPoProperties do
  it_behaves_like "PoPropertyable"

  it "can be built by a factory" do
    FactoryGirl.build("product_po_properties").should be_valid
  end

  describe "validates accessors"
  describe "other functionality" do
    let(:properties) { described_class.new }
    it "has_many line_items" do
      properties.line_items.should == []
      properties.line_items << build(:line_item, line_itemable: nil)
      properties.line_items.size.should == 1
    end

    it "sums line items for a price" do
      properties.line_items= [mock_model(LineItem, line_price: 123.45)]
      properties.price.should == 123.45
    end
  end
end

And when I run it, you can see that it runs the test to make sure that the object responds to price (as a general requirement for implementing "PoPropertyable"), and then a test to ensure that this particular object will calculate the price in the way I want it to (summing line items).

ProductPoProperties
  can be built by a factory
  other functionality
    has_many line_items
    sums line items for a price
  behaves like PoPropertyable
    implements po_propertyable
      reports a price

Finished in 0.15161 seconds
4 examples, 0 failures

Pretty awesome!