13

I am experiencing some baffling behavior in rspec and rspec-rails 2.11.0. I have reproduced the behavior on a co-worker's app running 2.7.1 (both on ruby 1.9.3)

These tests work as expected (fails):

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

Failure message is "result should not have changed, but did change from 0 to 2" in both cases

Changing the "from" in the expectation to a different value inexplicably makes it pass, rather than fail no matter what happens to the value of i in the expect block:

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

I've only recently upgraded to 1.9.3 and I can say with some certainty I would have noticed this behavior before if I had been experiencing it. Can anyone explain this and/or what I'm doing wrong?

Johnny C
  • 1,799
  • 1
  • 16
  • 27

1 Answers1

12

I don't think it does quite what you expect, but the way the tests are written doesn't really expose this. Your last value fails because it was never defined as 1.

The main step in revealing this is inverting the test.

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

This results in the first two tests passing, and the last test failing with the error result should have initially been 1, but was 0

So if we take the problem test as it was, you are saying is i should not change from 1 and since i is never 1, this test will never fail.

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
Alter Lagos
  • 12,090
  • 1
  • 70
  • 92
Gazler
  • 83,029
  • 18
  • 279
  • 245
  • By your logic, shouldn't the "not_to change from" test fail with the same message? How is it true, and thus passing, that something "is not changing from 1" if it's not 1 in the first place? Is there some documentation I'm missing here that explains this better? – Johnny C Oct 02 '12 at 20:41
  • @JCSG No, you are testing that the block does not change the value from 1, and since the value is never 1, the statement holds true. Does that make sense? When you test the positive case (`to_change`) that does require `from(i) == i` – Gazler Oct 02 '12 at 20:45
  • I guess the takeaway is to always have a separate test for the initial value if that's important. Anyways, thanks for your help. – Johnny C Oct 04 '12 at 14:21