Подтвердить что ты не робот

Rails: Как проверить state_machine?

Пожалуйста, помогите мне. Я смущен. Я знаю, как писать поведение модели, управляемое положением, но я не знаю, что мне писать в спецификациях...

Мой файл model.rb выглядит

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

Я использую state_machine gem.

Пожалуйста, покажите мне курс.

4b9b3361

Ответ 1

Вопрос старый, но у меня был тот же самый. Пример из 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

Мое решение было:

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

Я использовал:

  • ruby ​​(1.9.3)
  • рельсы (3.1.3)
  • rspec (2.8.0.rc1)
  • factory_girl (2.3.2)
  • state_machine (1.1.0)

Ответ 2

state_machine_rspec gem включает в себя множество вспомогательных методов для написания кратких спецификаций.

 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

Эти контроллеры RSpec помогут с параметрами state_machine с высокого уровня. Отсюда нужно написать спецификации для бизнес-кейсов для can_approve?, can_divert? и can_repeat?.

Ответ 3

Я написал специальный сопоставитель RSpec. Это позволяет проверять поток состояния элегантным и простым способом: проверить его

Ответ 4

К сожалению, я думаю, вам нужно поставить тест для каждого состояния → переход состояния, который может выглядеть как дублирование кода.

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 approved" do
    r = Ratification.new
    r.boss?.should == true
    r.approve
    r.owner?.should == true
    r.approve
    r.done?.should == true
  end

  # ...
end

К счастью, я думаю, что это обычно подходит для тестирования интеграции. Например, чрезвычайно простой конечный автомат для платежной системы:

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

У вас могут быть тесты модулей, как указано выше, но вы, вероятно, также проведете интеграционное тестирование, например:

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

Это было много рук, но, надеюсь, это имеет смысл. Я также не очень привык к RSpec, поэтому, надеюсь, я не допустил слишком много ошибок. Если есть более элегантный способ проверить это, я еще не нашел его.