Написание минимального теста спецификации модели для атрибутов настройки оператора case - PullRequest
0 голосов
/ 03 декабря 2018

Я пишу модельный тест в minitest-spec для следующего метода модели:

  def self.attributes_for_state(state)
    case state
    when :closed
      attributes = {
        active: false,
        selected: false,
        staged: false,
      }
    when :selected
      attributes = {
        active: true,
        selected: true,
        selected_at: Time.zone.now,
        staged: false,
        staged_at: nil,
      }
  else
      raise "Invalid state choice, no attributes defined for #{state}"
    end
  end

Я написал более ранний тест, в котором оператор атрибутов if определял состояние, но этот перевернулся -вместо этого состояние определяет атрибуты.Как настроить оператор case для списка атрибутов?У меня есть идея (ниже), но она туманна:

Предположим, я придерживаюсь структуры других тестов в моем файле спецификаций (describe / it)

describe "#attributes_for_state" do
  it "returns closed attributes when state is :closed" do
     # attributes_for_state(state)
    create ps = :product_selection, :closed #Factory/trait not registered
    assert_equal(ps.attributes_for_state(:closed), {active: false, selected: false, staged: false, staging: false, destaging: false,})
end

    end
    it "should have :selected attributes" do

    end
    it "should have :staged attributes" do

    end        
  end

Завод, для справки:

factory :product_selection do
  account {|ps| ps.association(:account) }
  user {|ps| ps.association(:user) }

 active { true }
 selected { false }
 staging { false }
 staged { false }
 staged_at { nil }    
end

1 Ответ

0 голосов
/ 04 декабря 2018

Я обычно располагаю спецификацию следующим образом:

describe 'method name' do
  subject { ... }

  context 'when some condition' do
    //define vars with 'let'

    //setup the mocks in a 'before' hook (only before each)

    it 'does something' do
      // Just check that the subject is what you expect
    end
  end
end

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

Таким образом, один из способов сделать это можно так:

describe "#attributes_for_state" do
  subject { described_class.attributes_for_state(state) }

  context 'when closed' do
    let(:state) { :closed }
    let(:expected_attr) do
      {
        active: false,
        selected: false,
        staged: false,
      }
    end
    it { should eq expected_attr }
  end

  context 'when selected' do
    let(:time_zone) { double(now: time) }
    let(:time) { 'some_time' }
    let(:state) { :selected }
    let(:expected_attr) do
      {
        active: true,
        selected: true,
        selected_at: time,
        staged: false,
        staged_at: nil,
      }
    end

    before do
      allow(Time).to receive(:zone).and_return(time_zone)
    end

    it { should eq expected_attr }
  end
end

По сути, верхнее описание должно быть с именем метода, а контекст - разделить ваш тест на разные случаи.Правило состоит в том, чтобы всегда начинать контекст с таких слов, как «когда» и «с» ...

Используйте тему, чтобы указать, что вы тестируете, в данном случае это результат метода и каждого контекста.определите его состояние и ожидаемые атрибуты.

Вы также можете проверить неопределенное состояние:

context 'when not defined' do
  let(:state) { "some_not_defined_state" }

  it 'raises runtime error' do
    expect { subject }.to raise_error(RuntimeError)
  end
end

При проверке на наличие ошибки важно указать, какой тип ошибки вы ожидаете ...

edit: Когда вы настраиваете спецификацию следующим образом, бонус заключается в том, что когда вы запускаете ее с guard, вы получаете некоторую документацию для своего кода:

enter image description here

...