Re: Stopping Example Execution?

n Sun, Jun 29, 2008 at 12:20 PM, David C. wrote:
On Jun 29, 2008, at 11:18 AM, Britt Mileshosky wrote:

However, do you see where something like a return statement or end
example statement could be beneficial?
If you are working from the top down with your controller action
execution, then you only need to test your expectation
and then bail out of your action. No need to further test or meet
requirements on anything else in that action because your
single test has been met.

  • in my example for making sure I find a user, I’d like to end execution
    once I DID find the user, i shouldn’t have to satisfy
    requirements about finding an account and a person… I’ll write those
    expectations later in another nested describe group, as you
    can see here, in a top down process

PeopleController with a logged in user

  • should find user

PeopleController with a logged in user who has an account

  • should find account

PeopleController with a logged in user who doesnt have an account

  • shouldn’t find account
  • should redirect …

PeopleController with a logged in user who has an account the person
belongs to

  • should find person
  • should assign person for the view

PeopleController with a logged in user who has an account the requested
person does not belong to

  • should not find person
  • should …

My instinct about this is that it would encourage long methods because
it would make it less painful to test them, so I would be adverse to
anything that let’s you short circuit the method.

Anybody else have opinions on that?

I’m just catching up on email now after being sick for the past six
days, but health aside my opinion is that I agree with David’s opinion.
Rather than focusing on how-to write easier tests that complain less,
start focusing on how-to write the right tests that complain when
necessary.

One of the benefits associated with feeling the pain of a test is that
it may be a sign to re-assess and refactor your code. This usually
happens early enough that it only takes a few minutes. Short circuiting
essentially gives you the ability to not feel the pain. Its like CIPA
[0], but for code. I would fear that the code would get so bad that by
the time the test cried with pain your code was already beyond easy
repair and instead required invasive surgery.

Tests are part of the nervous system of your application. When they
hurt, they’re telling you something isn’t right and that it should be
addressed,

I wouldn’t really say that anything I have been presenting has been a
result of ‘pains’,
more so an observation on how an example group with other example groups
can be much more readable
for myself and for other developers when they need to read the specs.
Stubbing everything at the top doesn’t
make complete sense. Why not stub inside the example group that has a
NICE describe statement telling you
what this stubbing is related to. We can’t do this because the first
examples will blow up due to having to execute
all the code.

Take the 2 examples:


PeopleController

stub everything way up here at the top where these

definitions are out of context (by means of position) with following

examples

stub controller requirments

stub logged in requirement

stub account requirement

stub no account requirement

stub account owns person

stub account doesn’t own person

PeopleController with before filters

  • should require user

PeopleController with a logged in user

  • should find user

PeopleController with a logged in user who has an account

  • should find account

PeopleController with a logged in user who doesnt have an account

  • shouldn’t find account
  • should redirect …

PeopleController with a logged in user who has an account the person
belongs to

  • should find person
  • should assign person for the view

PeopleController with a logged in user who has an account the requested
person does not belong to

  • should not find person
  • should …

PeopleController

stub the minimum needed to get to the first example group up and

running

PeopleController with before filters

  • should require user

PeopleController with a logged in user

stub logged in requirement

  • should find user

PeopleController with a logged in user who has an account

stub account requirement

  • should find account

PeopleController with a logged in user who doesnt have an account

stub no account requirement

  • shouldn’t find account
  • should redirect …

PeopleController with a logged in user who has an account the person
belongs to

stub account owns person

  • should find person
  • should assign person for the view

PeopleController with a logged in user who has an account the requested
person does not belong to

stub account doesn’t own person

  • should not find person
  • should …

I prefer the second group, but unfortunately I am not able to write my
specs in this organized fashion.
Just sayin.

Britt

On Mon, Jun 30, 2008 at 5:11 PM, Britt Mileshosky
[email protected] wrote:

requirements about finding an account and a person… I’ll write those expectations later in another nested describe group, as you

  • should redirect …

PeopleController with a logged in user who doesnt have an account

stub account owns person

I prefer the second group, but unfortunately I am not able to write my specs in this organized fashion.
Just sayin.

I appreciate the communication value you’re looking for, and you can
get it by stubbing everything you need to keep execution going
before(:each) example and then set message expectations
(should_receive) inside each example that help tell the story of that
example.

PeopleController

stub everything way up here at the top where these

definitions are out of context (by means of position) with following

examples

stub controller requirments

stub logged in requirement

stub account requirement

stub no account requirement

stub account owns person

stub account doesn’t own person

PeopleController with before filters

  • should require user

PeopleController with a logged in user

expect logged in query

  • should find user

PeopleController with a logged in user who has an account

expect logged in query

expect account query

  • should find account

etc

HTH,
David


To: [email protected]

and then bail out of your action. No need to further test or meet requirements on anything else in that action because your

  • should find account
  • should not find person
    One of the benefits associated with feeling the pain of a test is that it may be a sign to re-assess and refactor your code. This usually happens early enough that it only takes a few minutes. Short circuiting essentially gives you the ability to not feel the pain. Its like CIPA [0], but for code. I would fear that the code would get so bad that by the time the test cried with pain your code was already beyond easy repair and instead required invasive surgery.
    all the code.

stub account requirement

  • shouldn’t find account
  • should …
    example.

stub account doesn’t own person

expect account query

  • should find account

etc

HTH,
David

Yep, thats exactly what I’ve been practicing, and while its not exactly what I want, it does work nicely.
Thank you David

I’m gonna make another REALLY strong case for allowing the ability to
stop example execution and test code incrementally. I currently have
over 1700 examples for the current application I’m working on, and one
little line of code that I added in my App controller ( before_filter
:set_location ) brought on almost 1100 errors across my tests. Now I
know people will say that the requirements weren’t understood at the
beginning of the application and that it could have been avoided with
better planning… but this isn’t the case.

I now have to go into each of my controller tests and add the stub into
every before declaration to clear up my errors. Not fun, and could’ve
been avoided completely.

Britt

On Jul 2, 2008, at 9:58 PM, Britt Mileshosky wrote:

From: [email protected]

end example statement could be beneficial?
can see here, in a top down process

My instinct about this is that it would encourage long methods
tests that complain less, start focusing on how-to write the

for myself and for other developers when they need to read the
PeopleController

PeopleController with a logged in user who doesnt have an account

  • should not find person
    PeopleController with a logged in user
  • should redirect …
  • should not find person
    before(:each) example and then set message expectations

stub logged in requirement

  • should find user

my tests. Now I know people will say that the requirements weren’t
understood at the beginning of the application and that it could
have been avoided with better planning…

RSpec < BDD < Agile < Embrace Change. I don’t think you’d see that
argument here.

but this isn’t the case.

I now have to go into each of my controller tests and add the stub
into every before declaration to clear up my errors. Not fun, and
could’ve been avoided completely.

Yes, it could have, with the existing tools! Try this next time:

Spec::Runner.configure do |config|
config.before(:each, :type => :controller) do
controller.stub!(:set_location) if controller.respond_to?
(:set_location)
end
end

Hey Britt - I appreciate your passion for this feature, but I have to
say that I’m as passionately against it as you are for it, for reasons
I’ve cited and others have echoed.

That said, this is open source. If you want to make this happen then
you have a few options. You can write your own gem that extends rspec
to do it. You can even fork rspec and add it to your fork, though I
think we’d all be better served if you did it in a separate gem. In
either case, that would get you the feature you want and give other
people a chance to try it out. And if it evolves into an essential
feature that a lot of people find real value in, I’d be willing to
look at it again. But until such time as its proven itself otherwise,
this feature seems more potentially harmful than useful to me.

FWIW,
David


  • should find user
  • should assign person for the view

for myself and for other developers when they need to read the specs. Stubbing everything at the top doesn’t

PeopleController with a logged in user who has an account the person belongs to

PeopleController with a logged in user who has an account the requested person does not belong to
get it by stubbing everything you need to keep execution going

stub account requirement

PeopleController with a logged in user who has an account

expect logged in query

expect account query

  • should find account

etc

HTH,
David

Yep, thats exactly what I’ve been practicing, and while its not exactly
what I want, it does work nicely.
Thank you David

One good way (IMO) to approach before filters is to always stub them
when it
comes time to testing a controller action. And to test the filter
separately
in isolation. For example if you need to define an application level
before
filter in ApplicationController, then test the filter in isolation using
an
application_controller_spec.

If you’d like to know that your controllers which subclass
ApplicationController use them, you can easily add a declarative style
“it”
helper which verifies that the filter is being used, but doesn’t test
the
filter (since you already did that in your application_controller_spec.

I know this doesn’t help you now, but it is a useful technique which you
can
use in the future to limit the maintenance nightmare that can come along
with things like before filters,

Zach

On Wed, Jul 2, 2008 at 10:58 PM, Britt Mileshosky
[email protected]