2010-06-15 21 views
16

Proszę, pomóż mi. Jestem zmieszany. Wiem, jak napisać zachowanie stanu napędzane modelu, ale nie wiem co mam napisać w specyfikacji ...Szyny: Jak przetestować state_machine?

Mój plik model.rb wyglądać

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 

używam state_machine gem.

Proszę, pokaż mi kurs.

+0

Jakikolwiek sposób to zrobić bez uderzania w bazę danych? Wygląda na to, że powinniśmy być w stanie wykluczyć dowolne urządzenie state_machine, aby trafić do bazy danych i nadal otrzymywać wszystkie oczekiwane przez nas zmiany. –

Odpowiedz

0

Niestety, myślę, że trzeba umieścić test dla każdego stanu -> przejście do stanu, które może wyglądać jak powielanie kodu.

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 

Na szczęście, myślę, że zwykle pasuje do testów integracyjnych. Na przykład, bardzo prosta maszyna stanu dla systemu płatniczego będzie:

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 

Możecie jeszcze testy jednostkowe jak wyżej, ale prawdopodobnie będziesz mieć również testy integracyjne, coś jak:

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 

To było dużo zręczności, ale mam nadzieję, że ma to sens. Nie jestem też bardzo przyzwyczajony do RSpec, więc mam nadzieję, że nie popełniłem tam zbyt wielu błędów. Jeśli istnieje bardziej elegancki sposób na sprawdzenie tego, nie znalazłem go jeszcze.

+2

Możesz użyć ... @ account.recent_bill.should be_unpaid –

9

Pytanie jest stare, ale miałem ten sam. Biorąc przykład z state_machine gem:

class Vehicle 
    state_machine :state, :initial => :parked do 
    event :park do 
     transition [:idling, :first_gear] => :parked 
    end 

    event :ignite do 
     transition :stalled => same, :parked => :idling 
    end 

    event :idle do 
     transition :first_gear => :idling 
    end 

    event :shift_up do 
     transition :idling => :first_gear, :first_gear => :second_gear, :second_gear => :third_gear 
    end 

    event :shift_down do 
     transition :third_gear => :second_gear, :second_gear => :first_gear 
    end 
    end 
end 

My roztwór:

describe Vehicle do 

    before :each do 
    @vehicle = Factory(:vehicle) 
    end 

    describe 'states' do 
    describe ':parked' do 
     it 'should be an initial state' do 
     # Check for @vehicle.parked? to be true 
     @vehicle.should be_parked 
     end 

     it 'should change to :idling on :ignite' do 
     @vehicle.ignite! 
     @vehicle.should be_idling 
     end 

     ['shift_up!', 'shift_down!'].each do |action| 
     it "should raise an error for #{action}" do 
      lambda {@job_offer.send(action)}.should raise_error 
     end 
     end 
    end 
    end 
end 

ja z:

  • Ruby (1.9.3)
  • szyny (3.1.3)
  • rspec (2.8.0.rc1)
  • factory_g IRL (2.3.2)
  • state_machine (1.1.0)
1

Napisałem rspec dopasowywania niestandardową. Pozwala przetestować przepływ stanu w elegancki i prosty sposób: check it out

2

Klejnot state_machine_rspec zawiera wiele pomocnych metod do pisania zwięzłych specyfikacji.

describe Ratification do 
    it { should have_states :boss, :declarant, :done, :owner } 
    it { should handle_events :approve, when: :boss } 
    it { should handle_events :approve, when: :owner } 
    it { should handle_events :divert, when: :boss } 
    it { should handle_events :divert, when: :owner } 
    it { should handle_events :repeat, when: :declarant } 
    it { should reject_events :approve, :divert, :repeat, when: :done } 
    it { should reject_events :approve, :divert, :repeat, when: :done } 
end 

te dopasowujące rspec pomoże z state_machine specyfikacji z wysokiego poziomu. Stąd trzeba napisać specyfikacje dla przypadków biznesowych dla can_approve?, can_divert? i can_repeat?.