setups get run multiple times, big issue with RR #31

Closed
DouglasMeyer opened this Issue Apr 18, 2011 · 7 comments

Comments

Projects
None yet
4 participants
@DouglasMeyer

Hey Guys-

I ran into this issue when I was using a RR mock in a parent context's setup (see example).

require '.....'
context "bla" do
  setup do
    puts "SETUP"
    Object.new.tap do |obj
      mock(obj).something{ true }
    end
  end
  context "a context" do
    should :something
  end
end

Output:

SETUP
bla a context
SETUP
  - should something: something() Called 0 times. Expected 1 times.

It looks like the setup is getting called for the bla context, then once again for the a context context. I would guess a way to fix this is to not have the contexts run the setups and teardowns, but have the "runnables" run them.

Thanks,
-Doug

@achiu

This comment has been minimized.

Show comment Hide comment
@achiu

achiu Apr 18, 2011

Contributor

The parent context setup are ran again within each child context. So your a context context is going to setup the mocks again. One way you can avoid this is to do the mocking within the assertion that your testing, or not nest the context that you don't want the mocking to be also ran on.

Contributor

achiu commented Apr 18, 2011

The parent context setup are ran again within each child context. So your a context context is going to setup the mocks again. One way you can avoid this is to do the mocking within the assertion that your testing, or not nest the context that you don't want the mocking to be also ran on.

@DouglasMeyer

This comment has been minimized.

Show comment Hide comment
@DouglasMeyer

DouglasMeyer Apr 18, 2011

You may be right in the case of the example, but it is still an issue that riot needlessly runs setup/teardown multiple times. This issue is easily missed unless the setup/teardown takes a while or you use RR.

You may be right in the case of the example, but it is still an issue that riot needlessly runs setup/teardown multiple times. This issue is easily missed unless the setup/teardown takes a while or you use RR.

@toothrot

This comment has been minimized.

Show comment Hide comment
@toothrot

toothrot Apr 18, 2011

Member

This is actually intentional: here is an example from an old discussion

If you think about it, each context is sort of its own world. The sub-context has to re-run them since the previous context will have cleaned up after itself in its teardowns, ideally.

Member

toothrot commented Apr 18, 2011

This is actually intentional: here is an example from an old discussion

If you think about it, each context is sort of its own world. The sub-context has to re-run them since the previous context will have cleaned up after itself in its teardowns, ideally.

@DouglasMeyer

This comment has been minimized.

Show comment Hide comment
@DouglasMeyer

DouglasMeyer Apr 18, 2011

Ok, I think I have a good idea of the model. So it looks like this isn't so much an issue with contexts as it is how RR is used. As this example should show, if there aren't any assertions in the parent context, the expectations from the setup are never reset.

Ok, I think I have a good idea of the model. So it looks like this isn't so much an issue with contexts as it is how RR is used. As this example should show, if there aren't any assertions in the parent context, the expectations from the setup are never reset.

@gus

This comment has been minimized.

Show comment Hide comment
@gus

gus Mar 22, 2012

Member

Hey Doug,

Sorry for the much belated response. I agree with you that there is a problem. The tests should pass whether you comment out the first should :get_mocked_once or not.

What's strange is that if I do this, it works:

require 'rubygems'
require 'riot'
require 'riot/rr'

context "riot sanity test" do
  #setup do
    #puts "SETUP"
    #Object.new.tap do |obj|
      #mock(obj).get_mocked_once{ true }
    #end
  #end

  #un-comment this next line and the tests magically pass
  #should :get_mocked_once
  context "generic context" do
    setup do
      puts "SETUP"
      Object.new.tap do |obj|
        mock(obj).get_mocked_once{ true }
      end
    end

    should "call get mocked once" do 
      topic.get_mocked_once
    end
  end
end

Taking a look.

Member

gus commented Mar 22, 2012

Hey Doug,

Sorry for the much belated response. I agree with you that there is a problem. The tests should pass whether you comment out the first should :get_mocked_once or not.

What's strange is that if I do this, it works:

require 'rubygems'
require 'riot'
require 'riot/rr'

context "riot sanity test" do
  #setup do
    #puts "SETUP"
    #Object.new.tap do |obj|
      #mock(obj).get_mocked_once{ true }
    #end
  #end

  #un-comment this next line and the tests magically pass
  #should :get_mocked_once
  context "generic context" do
    setup do
      puts "SETUP"
      Object.new.tap do |obj|
        mock(obj).get_mocked_once{ true }
      end
    end

    should "call get mocked once" do 
      topic.get_mocked_once
    end
  end
end

Taking a look.

@gus

This comment has been minimized.

Show comment Hide comment
@gus

gus Mar 22, 2012

Member

Even "funnier" is this:

require 'rubygems'
require 'riot'
require 'riot/rr'

context "riot sanity test" do
  setup do
    puts "SETUP"
    Object.new.tap do |obj|
      mock(obj).get_mocked_once{ puts "here"; true }
      puts obj.inspect
    end
  end

  #should :get_mocked_once

  context "with subcontext" do
    should "x" do
      topic.get_mocked_once
      topic.get_mocked_once
    end
  end
end

Which generates this message:

situation/on
SETUP
riot sanity test with subcontext
SETUP
  ! should x: get_mocked_once()
Called 2 times.
Expected 1 times.

0 passes, 0 failures, 1 errors in 0.005137 seconds

So, in this case it sees that's it been called two times. Quite fishy indeed.

Member

gus commented Mar 22, 2012

Even "funnier" is this:

require 'rubygems'
require 'riot'
require 'riot/rr'

context "riot sanity test" do
  setup do
    puts "SETUP"
    Object.new.tap do |obj|
      mock(obj).get_mocked_once{ puts "here"; true }
      puts obj.inspect
    end
  end

  #should :get_mocked_once

  context "with subcontext" do
    should "x" do
      topic.get_mocked_once
      topic.get_mocked_once
    end
  end
end

Which generates this message:

situation/on
SETUP
riot sanity test with subcontext
SETUP
  ! should x: get_mocked_once()
Called 2 times.
Expected 1 times.

0 passes, 0 failures, 1 errors in 0.005137 seconds

So, in this case it sees that's it been called two times. Quite fishy indeed.

@DouglasMeyer

This comment has been minimized.

Show comment Hide comment
@DouglasMeyer

DouglasMeyer Mar 22, 2012

Thanks for looking into this inconsistency.

Thanks for looking into this inconsistency.

@gus gus closed this in 0ac61bf Apr 19, 2012

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment