rspec not_to изменить поведение не так, как ожидалось

Я испытываю некоторую непонятливость в rspec и rspec-rails 2.11.0. Я воспроизвел поведение в приложении коллеги, работающем под управлением 2.7.1 (оба на Ruby 1.9.3).

Эти тесты работают, как ожидалось (не работают):

it "should not change i" do
    i = 0
    expect {
      i = 2
    }.not_to change { i }
end

it "should not change i" do
    i = 0
    expect {
      i = 2
    }.not_to change { i }.from( 0 )
end

Сообщение об ошибке: «результат не должен был измениться, но изменился с 0 на 2» в обоих случаях.

Изменение «from» в ожидании на другое значение необъяснимо заставляет его пройти, а не потерпеть неудачу, независимо от того, что происходит со значением i в блоке ожидания:

it "should not change i" do
    i = 0
    expect {
        i = 2
    }.not_to change { i }.from( 1 )
end

Я только недавно обновился до 1.9.3 и могу сказать с некоторой уверенностью, что заметил бы такое поведение раньше, если бы испытывал его. Может ли кто-нибудь объяснить это и / или что я делаю не так?


person Johnny C    schedule 02.10.2012    source источник


Ответы (1)


Я не думаю, что он делает то, что вы ожидаете, но то, как написаны тесты, на самом деле этого не раскрывает. Ваше последнее значение не работает, потому что оно никогда не определялось как 1.

Главный шаг в обнаружении этого - инвертирование теста.

describe "stuff" do

  it "should not change i" do
      i = 0
      expect {
        i = 2
      }.to change { i }
  end

  it "should not change i" do
      i = 0
      expect {
        i = 2
      }.to change { i }.from( 0 )
  end


  it "should not change i" do
      i = 0
      expect {
          i = 2
      }.to change { i }.from( 1 )
  end

end

В результате первые два теста пройдут, а последний тест завершится с ошибкой result should have initially been 1, but was 0.

Итак, если мы возьмем проблемный тест в том виде, в каком он был, вы говорите, что это i should not change from 1, а поскольку i никогда не равно 1, этот тест никогда не завершится ошибкой.

it "should not change i" do
    i = 0
    expect {
        i = 2
    }.not_to change { i }.from( 1 ) # i goes from 0 to 2, not 1 to 2, so the test is valid
end
person Gazler    schedule 02.10.2012
comment
По вашей логике, не должно ли not_to измениться из теста с тем же сообщением? Как это правда, и, таким образом, преходящее, что что-то не меняется с 1, если это не 1 в первую очередь? Есть ли какая-то документация, которая мне здесь не хватает, чтобы лучше это объяснить? - person Johnny C; 03.10.2012
comment
@JCSG Нет, вы проверяете, что блок не изменяет значение с 1, а поскольку значение никогда не равно 1, утверждение верно. Имеет ли это смысл? Когда вы проверяете положительный случай (to_change), который требует from(i) == i - person Gazler; 03.10.2012
comment
Я предполагаю, что вывод - всегда иметь отдельный тест для начального значения, если это важно. В любом случае, спасибо за вашу помощь. - person Johnny C; 04.10.2012