Before and After blocks for individual feature files?


#1

Hi – is it possible to set before and after blocks for individual
feature
files?
I’ve tried putting them in step files, but they just get called before
everything, like they’d been declared in env.rb, which is consistent
with
how I thought cucumber worked, but I thought I’d best try it anyway.
Anyway, I have some features that require a specific state be set up
before
they run – is this possible to do, and how would I go about doing it?
Thanks for any & all help,
Doug.


#2

Perhaps use background?

Julian.


#3

Brilliant, cheers!
Doug.

2009/4/28 Julian L. removed_email_address@domain.invalid


#4

Hi – is it possible to set before and after blocks for individual feature
files?

Yes. Use tagged hooks:
http://wiki.github.com/aslakhellesoy/cucumber/hooks

Aslak


#5

I also would like a hook that executes a block once before running a
feature file.

In my testing i found that:

  • Background: executes before each scenario
  • Before executes before each scenario
  • Before(’@tag’) executes before each scenario

Is there a way to execute a block once before each feature, but not
before each scenario?


#6

On Tue, Apr 28, 2009 at 5:32 PM, Arco removed_email_address@domain.invalid wrote:

No :slight_smile:


#7

On Tue, Apr 28, 2009 at 6:15 PM, Arco removed_email_address@domain.invalid wrote:

is run before the other scenarios in my feature file…

@first
Scenario: Call a before block before running other scenarios…

But this puts junk in my feature files. Is there a better, cleaner
way??

a) Why do you need one thing to happen before a feature?
b) Why can’t you do it before each scenario?

Aslak


#8

OK - I found a workaround. I simply tag the first scenario with
@first’, then
do Before(’@first’) and i get what I want - executing a block once for
the feature file.

Except for one problem: most of my scenarios are done as scenario
outlines, which
are run multiple times - once for each row of my Example table.

A workaround to that problem might be to put a ‘dummy’ scenario that
is run before the other scenarios in my feature file…

@first
Scenario: Call a before block before running other scenarios…

But this puts junk in my feature files. Is there a better, cleaner
way??


#9

I’d like to do this:

Feature: user signup
Before:
Given I have a cleaned up database
Scenario Outline: Sign Up
Given I am on the signup page
When I sign up using
Then I should see
Examples:
|userid |message |
|userX |successful signup |
|userX |duplicate userid |

“I have a cleaned up database” runs before every example, making the
second example (‘duplicate userid’) fail.


#10

Thanks for your reply Ben. +1 on your wording recommendation - I
understand and agree 100%

However - for me - the Background block executes before each example
in the table. Therefore, the database is cleared twice, and the
second example (‘duplicate userid’) fails.

(Cucumber 0.3.1 / ruby 1.8.7 (2008-08-11 patchlevel 72) [i386-cygwin])

Here are some snippets from a little workaround that i’ve employed…
in env.rb:
State = {‘feature_file’=>‘initialize’}
in my_steps.rb:
unless State[‘feature_file’] ==
@__cucumber_current_step.file_colon_line.split(’:’).first
puts “CLEANUP CODE HERE - RUN ONCE PER FEATURE FILE --------”
end
State[‘feature_file’] =
@__cucumber_current_step.file_colon_line.split(’:’).first

I’m sure there must be a better way! I am still learning cucumber so
any advice is welcome!
:wink:


#11
|userid     |message           |
|userX      |successful signup |
|userX      |duplicate userid  |

Feature: user signup

Scenario: succesful signup
When I sign up using Kero
Then I should see welcome Kero

Scenario: failed signup of existing user
Given there is a user Kero
When I sign up using Kero
Then I should see trying to impersonate someone else

NB: yes, clean the database before every scenario

Bye,
Kero.


How can I change the world if I can’t even change myself?
– Faithless, Salva Mea


#12

Hey Ben,

It’d be kinda cool if there was a sort of before and after for a
feature rather than each scenario. Is there?

(Rails context) We often need this. It’d be really helpful for things
like when we want to test about 15 things on a particular web page,
and they don’t require fresh data. We end up with a login and setup
type background which gets run every time rather than simply once.

I guess we could refactor it into a set of examples perhaps… would
that work? It just strikes me as quite complicated. It’d be awesome if
we had sub-scenarios (and they could be specified to levels) :wink:
Perhaps I’m just being too complicated.

I loved your rubyconf talk presentation, BTW. We kinda took exception
to the bit where you said “Selenium just works”, though. There are a
number of things where the connection between selenium and webrat is a
little tenuous and finicky about.

Also we seem to be having timing issues for AJAX requests with
Selenium. Webrat doesn’t seem to want to wait until the AJAX request
as finished before doing the next thing. Any ideas here?

Julian.


#13

Arco wrote:

|userid     |message           |
|userX      |successful signup |
|userX      |duplicate userid  |

“I have a cleaned up database” runs before every example, making the
second example (‘duplicate userid’) fail.

You could use Background and it would work just like you want it to:

Feature: user signup
Background:
Given I have a cleaned up database
Scenario Outline: Sign Up
Given I am on the signup page
When I sign up using
Then I should see
Examples:
|userid |message |
|userX |successful signup |
|userX |duplicate userid |

However, I would not encourage this. You should try to avoid using
technical words, such as database, in your features. If anything you
could say “Given no users exist” or something like that. Keeping your
database clean is something you generally want for every scenario
though. So I would suggest putting the code in your “Given I have a
cleaned up database” code into a Before block. The wiki has a page on
using the Before hook:
http://wiki.github.com/aslakhellesoy/cucumber/hooks

Basically, in your env.rb file you will add something like:

Before do
Database.clean! # or however you clean your DB
end

HTH,
Ben


#14

Arco wrote:

in env.rb:
any advice is welcome!
:wink:

While the above code is clever I would discourage its use. IMO, it
looks like you are trying too hard to phrase your scenarios all within a
single scenario outline. In this case I would not use tables but I
would have separate scenarios. For example:

Feature: user signup

Scenario: success
Given I am on the signup page

When I enter valid registration information
And I press "Register"

Then I should see "You have signed up successfully!"

Scenario: duplicate user with email # dunno, what really qualifies as
duplicate for you…
Given I am on the signup page
And a user with email “removed_email_address@domain.invalid” exists

When I enter valid registration information
And I fill in "Email" with "removed_email_address@domain.invalid"
And I press "Register"

Then I should see "A user has already signed up with removed_email_address@domain.invalid"

Does that make sense? Basically, whenever you feel the need to embed a
conditional in your scenario it means you need a separate one. You can
sometimes accomplish this by using scenario tables but that constrains
you to the same setup steps. In your case you wanted additional context
for one of your scenarios in the table… this means that you probably
should have a whole new scenario like above. Your current solution
obfuscates the additional context and therefore looses some of the
documentation value that Cucumber offers.

FWIW.

Oh, and please try not to top-post in the future - it makes threads hard
to follow. :slight_smile:

-Ben


#15

Julian L. wrote:

Hey Ben,

It’d be kinda cool if there was a sort of before and after for a
feature rather than each scenario. Is there?

Nope. There is no before(:all) equivalent in cucumber. Just the Before
and After hooks, which are for scenarios… and Backgrounds which are
just for scenarios on the given feature.

(Rails context) We often need this. It’d be really helpful for things
like when we want to test about 15 things on a particular web page,
and they don’t require fresh data. We end up with a login and setup
type background which gets run every time rather than simply once.
In the context of webrat a before(:all) would not help you a whole lot
since each scenario starts with a new session (so you have to login each
time, for example). I understand the argument for complex data setup
though. Having the same setup ran for each scenario can get costly. I
haven’t felt enough pain though to really justify adding something like
that. Cleanup would be messy because we couldn’t wrap it all in a
transaction AFAIK, so you would have to have an after(:all) like method
to clean up the feature. For complex data that I rely on all the time I
tend to load it once with fixtures at boot up time within env.rb. This
is usually for look-up data… but if you were really concerned about
record creation you could do something similar. The question is if the
additional complexity of keeping all that global state in your head
worth the faster execution time. For me it generally is not.

I guess we could refactor it into a set of examples perhaps… would
that work? It just strikes me as quite complicated. It’d be awesome if
we had sub-scenarios (and they could be specified to levels) :wink:
Perhaps I’m just being too complicated.

I would need more context to really answer your question. However, can
I ask if your scenarios are written in a declarative or imperative
fashion[1]? If they are written declaratively, or at least partly, then
you can specify a lot more behavior in a step without adding too much
noise to the scenario. Another thing I should point out is that you
don’t need to, and you shouldn’t, test everything on the Cucumber
level. For complex views, for example, it may be easier to do RSpec
examples (view specs) and just use Cucumber to test the basics. In
general, I’m pretty wary about sub-scenarios and the like. They could
be powerful, but they could very easily get complicated and turn
scenarios into a giant mess that only programmers could understand.
Feel free to share any ideas you have on the subject though and we’ll
see what the tradeoffs are. We love throwing new ideas around on the
list. :slight_smile:

I loved your rubyconf talk presentation, BTW. We kinda took exception
to the bit where you said “Selenium just works”, though. There are a
number of things where the connection between selenium and webrat is a
little tenuous and finicky about.

Thanks! Yeah, the selenium adapter in webrat isn’t nearly as mature as
the rails adapter. :frowning: I haven’t had a lot of issues with it, but I try
to use it as least as possible and have only really used it on simple
things. And to be honest, I haven’t used it since January. So, YMMV.

Also we seem to be having timing issues for AJAX requests with
Selenium. Webrat doesn’t seem to want to wait until the AJAX request
as finished before doing the next thing. Any ideas here?
I think I have seen people in #webrat on irc.freenode.net talk about
that and how they’ve had to add additional wait commands in. But, I
really don’t know any details. Sorry! Your best bet is to ask in
#webrat, or on it’s google group or lighthouse account.

-Ben

http://www.benmabey.com/2008/05/19/imperative-vs-declarative-scenarios-in-user-stories/


#16

Hey Ben,

It’d be kinda cool if there was a sort of before and after for a feature
rather than each scenario. Is there?

I think that would be particularly uncool actually, because people
would
start using it without understanding the implications.
Implications: Coupled, brittle scenarios.

Why do you think it would be useful?

Aslak


#17

After some consideration, I agree with Aslak’s and Ben’s advice
against keeping context across an entire feature.

But I am still not convinced that it makes sense for create a new
context for each row of an example table. As a newbie, I expected the
Before: block would be run once before the scenario, not once before
every row of the example table. (so did Ben initially…)

Approach A -----------------------
Before:
Given I have a clean database
Scenario Outline: Signup Scenarios
Given I start on the login page
When I signup as
Then I should see
Examples:
| userid | message |
| userA | successful signup |
| userA | error: duplicate userid |

Approach B ------------------------
Before:
Given I have a clean database
Scenario: Successful Signup
Given I start on the login page
When I signup as “userA”
Then I should see “successful signup”
Scenario: Failure - Duplicate Userid
Given I start on the login page
When I signup as “userA”
And I signup again as “userA”
Then I should see “error: duplicate userid”

OK I will use Approach B, but ideally would prefer to use Approach A,
and personally find it easier to read and understand.

Thanks again for your feedback! :slight_smile:


#18

On Apr 29, 2009, at 8:45 AM, Arco wrote:

When I signup as
Then I should see
Examples:
| userid | message |
| userA | successful signup |
| userA | error: duplicate userid |

To me, “Examples” means separate, independent items.

If these are to be run under the same scenario in sequence, then the
table should be called something else, maybe “Sequence:” or “Steps:”

There might be other use cases for such a feature… I don’t have any
to suggest at the moment, just brainstorming.

Andrew V.


#19

On Wed, Apr 29, 2009 at 8:45 AM, Arco removed_email_address@domain.invalid wrote:

| userA | error: duplicate userid |

If the desired behavior is sequential, then (to me), this is not a list
of
examples, but just a single example. So I’d find the separate scenarios
more
intention-revealing. If “Examples” were called “Steps,” that would
describe
what you’re going for in this particular case.

///ark


#20

Hey ben,

Selenium is slow, and we have a lot of
Ajax, so I’m just looking at ways to speed it up. Tags will be my
first port of call and splitting out between automated and simulated.
It irks me we can’t then simply run all our tests with one simple
cucumber command -we need two. It’d be nice if webrat could switch
between browser types per scenario or per feature. Sigh.

Blog: http://random8.zenunit.com/
Learn rails: http://sensei.zenunit.com/