ruby-on-rails rspec state-machine

ruby on rails - Rieles: ¿Cómo probar state_machine?



ruby-on-rails rspec (4)

Desafortunadamente, creo que es necesario realizar una prueba para cada estado -> transición de estado, que puede parecer una duplicación de código.

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

Afortunadamente, creo que esto generalmente encaja en las pruebas de integración. Por ejemplo, una máquina de estado extremadamente simple para un sistema de pagos sería:

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

Es posible que aún tengas las pruebas unitarias como anteriormente, pero probablemente también tengas pruebas de integración, algo como:

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

Eso fue un montón de mano en espera, pero espero que tenga sentido. Tampoco estoy muy acostumbrado a RSpec, así que espero no haber cometido demasiados errores allí. Si hay una forma más elegante de probar esto, todavía no la he encontrado.

Por favor, ayúdame. Estoy confundido. Sé cómo escribir el comportamiento del modelo impulsado por el estado, pero no sé qué debo escribir en las especificaciones ...

Mi archivo model.rb mira

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

Yo uso la gema state_machine .

Por favor, muéstrame el curso.


He escrito un emparejador personalizado RSpec. Permite probar el flujo de estado de manera elegante y simple: échale un vistazo


La gema state_machine_rspec incluye muchos métodos de ayuda para escribir especificaciones concisas.

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

Estos emparejadores RSpec ayudarán con las especificaciones de state_machine desde un alto nivel. A partir de aquí, ¿hay que escribir las especificaciones para los casos de negocio para can_approve? , can_divert? y can_repeat? .


La pregunta es vieja, pero yo tenía la misma. Tomando el ejemplo de la gema state_machine :

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

Mi solución fue:

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

Estaba usando

  • rubí (1.9.3)
  • rieles (3.1.3)
  • rspec (2.8.0.rc1)
  • factory_girl (2.3.2)
  • state_machine (1.1.0)