views:

33

answers:

1

Please, help me. I'm confused. I know how to write state-driven behavior of model, but I don't know what should I write in specs...

My model.rb file look

class Ratification < ActiveRecord::Base
  belongs_to :user

  attr_protected :status_events

  state_machine :status, :initial => :boss do
    state :boss
    state :owner
    state :declarant
    state :done

    event :approve do
      transition :boss => :owner, :owner => :done
    end

    event :divert do
      transition [:boss, :owner] => :declarant
    end

    event :repeat do
      transition :declarant => :boss
    end

  end
end

I use state_machine gem.

Please, show me the course.

A: 

Unfortunately, I think you need to put a test for each state -> state transition, which might feel like code duplication.

describe Ratification do
  it "should initialize to :boss" do
    r = Ratification.new
    r.boss?.should == true
  end

  it "should move from :boss to :owner to :done as it's approved" do
    r = Ratification.new
    r.boss?.should == true
    r.approve
    r.owner?.should == true
    r.approve
    r.done?.should == true
  end

  # ...
end

Fortunately, I think this usually fits into integration testing. For instance, an extremely simple state machine for a payments system would be:

class Bill < ActiveRecord::Base
  belongs_to :account

  attr_protected :status_events

  state_machine :status, :initial => :unpaid do
    state :unpaid
    state :paid

    event :mark_as_paid do
      transition :unpaid => :paid
    end
  end
end

You might still have the unit tests as above, but you'll probably also have integration testing, something like:

describe Account do
  it "should mark the most recent bill as paid" do
    @account.recent_bill.unpaid?.should == true
    @account.process_creditcard(@credit_card)
    @account.recent_bill.paid?.should == true
  end
end

That was a lot of handwaiving, but hopefully that makes sense. I'm also not super used to RSpec, so hopefully I didn't make too many mistakes there. If there's a more elegant way to test this, I haven't found it yet.

Jon Smock