rspec @variable возвращает ноль

У меня проблема с моей переменной @attributes. Я хотел бы, чтобы он был доступен, чтобы мой код оставался сухим, но в настоящее время мне нужно переопределить переменную и установить для нее «значения», чтобы мой тест rspec работал. Как лучше сделать это без дублирования значений.

ref: Неожиданная нулевая переменная в RSpec

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

describe "When one field is missing invalid " do 
    before(:each) do 
        @user = create(:user)
        @attributes = {"has_car"=>"true", "has_truck"=>"true", "has_boat"=>"true", "color"=>"blue value", "size"=>"large value"}
    end
  values = {"has_car"=>"true", "has_truck"=>"true", "has_boat"=>"true", "color"=>"blue value", "size"=>"large value"}
  values.keys.each do |f|
    p = values.except(f) 
    it "returns invalid when #{f.to_s} is missing" do 
              cr = CarRegistration::Vehicle.new(@user, p)
        cr.valid?
    end
  end
end

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

Обновление: я пытался использовать let(),

  describe "When one field is missing" do

        let(:user) {Factorybot.create(:user)}
        let(:attributes) = {{"has_car"=>"true", "has_truck"=>"true", "has_boat"=>"true", "color"=>"blue value", "size"=>"large value"}}

      attributes do |f|
        p = attributes.except(f) 
        it "returns invalid when #{f.to_s} is missing" do 
                  cr = CarRegistration::Vehicle.new(user, p)
            cr.valid?
        end
      end
  end

но получить следующую ошибку.

attributes недоступен для примера группы (например, блока describe или context). Он доступен только из отдельных примеров (например, блоков it) или из конструкций, которые выполняются в рамках примера (например, before, let и т. д.).


person user2012677    schedule 03.03.2019    source источник
comment
Вы можете запустить зацикливание ключей ВНУТРИ блока it, таким образом вам не нужно будет дублировать @attributes с переменной 'values'.   -  person BKSpurgeon    schedule 03.03.2019
comment
@BKSpurgeon Любые рекомендации по повторному использованию ключей вне блока и для других?   -  person user2012677    schedule 04.03.2019
comment
попробуйте использовать вспомогательные методы let, чтобы разрешить повторное использование вне блока: relishapp.com/rspec/rspec-core/docs/helper-methods/let-and-let   -  person BKSpurgeon    schedule 05.03.2019
comment
@BKSpurgeon, я попытался позволить и получил указанную выше ошибку.   -  person user2012677    schedule 06.03.2019
comment
обратитесь к моему ответу ниже или, альтернативно, следуйте ответу Серджио.   -  person BKSpurgeon    schedule 06.03.2019


Ответы (3)


В любом из ваших фрагментов вам не нужно attributes внутри ваших спецификаций. Это данные для генерирования спецификаций. Таким образом, он должен жить на один уровень выше.

describe "When one field is missing" do

  let(:user) { Factorybot.create(:user) }

  attributes = { "has_car" => "true", "has_truck" => "true", "has_boat" => "true", "color" => "blue value", "size" => "large value" }

  attributes do |f|
    p = attributes.except(f)
    it "returns invalid when #{f.to_s} is missing" do
      cr = CarRegistration::Vehicle.new(user, p)
      cr.valid?
    end
  end
end
person Sergio Tulentsev    schedule 06.03.2019
comment
я случайно отредактировал этот ответ. пожалуйста, вернитесь к исходной версии. извинения. - person BKSpurgeon; 06.03.2019
comment
@BKSpurgeon: не беспокойтесь :) К вашему сведению, этот подход (перебор структуры данных и создание нескольких блоков it) довольно широко используется. Делает кристально чистые журналы отказов. В отличие от вашей версии;) (которая приведет к тому, что ожидаемое значение false будет истинным) - person Sergio Tulentsev; 06.03.2019
comment
@BKSpurgeon: хорошая мысль о том, что в спецификации отсутствует фактическое утверждение! Не заметил. - person Sergio Tulentsev; 06.03.2019
comment
вы на 100% правы, я добавил примечание в пользу ОП. - person BKSpurgeon; 06.03.2019

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

person smathy    schedule 03.03.2019

Использование пусть

describe "When one field is missing" do
  let(:user) {Factorybot.create(:user)}
  let(:attributes) = {{"has_car"=>"true", "has_truck"=>"true", "has_boat"=>"true", "color"=>"blue value", "size"=>"large value"}}
  ## The variables are used INSIDE the it block.
  it "returns invalid when a key is missing" do
    attributes do |f|
      p = attributes.except(f)
      cr = CarRegistration::Vehicle.new(user, p)
      expect(cr.valid?).to eq(true)  # are you testing the expectation? Added this line.    
    end
  end
end

Лично мне не нравится писать тест (как выше), который может провалиться по нескольким причинам. Серджио прав. Но если вы хотите использовать let, вы должны использовать его ВНУТРИ блока it - этот пример показывает это.

person BKSpurgeon    schedule 06.03.2019