Passing context in Behave between scenarios

4,568 views
Skip to first unread message

Jacob G

unread,
Jan 16, 2015, 12:41:35 PM1/16/15
to behaviordriv...@googlegroups.com
Using Behave, I am trying to pass information between scenarios within a feature.  In scenario 1, the output of my test is a port number, which I need in scenario 2 in order to test additional functionality.  Here is how context is described by the Behave documentation:

class behave.runner.Context(runner)
Hold contextual information during the running of tests.
This object is a place to store information related to the tests you’re running. You may add arbitrary attributes to it of whatever value you need.
During the running of your tests the object will have additional layers of namespace added and removed automatically. There is a “root” namespace and additional namespaces for features and scenarios. 

Because the layers of namespace are removed automatically, I can't just do "context.port = value" in scenario 1, since that value is blown away before scenario 2 starts.  Is there a way, within a scenario, to set something at a different namespace level within context?

I was able to do a rather hacky work around for this, in which I use before_all in environment.py to do "context.port = []".  Then I can call "context.port.append(value)" in scenario 1 and access "context.port[0]" in scenario 2, but I'd really like a clean way to do this using the namespaces of context correctly.

Thanks,
Jacob 

Andrew Premdas

unread,
Jan 16, 2015, 2:38:12 PM1/16/15
to behaviordriv...@googlegroups.com
Passing information between scenarios is a really bad idea. Scenarios are meant to be executed in isolation, this makes them repeatable and dependable. Linking them together breaks this. Instead implement the first scenario, and get it too work, then use that mechanism in the second scenario

Scenario 1
   Do foo
   Do bar

Scenario 2
   Given scenario 1
   Do whatever

The cost you pay in another execition of the stuff in scenario 1 is well worth paying for a dependable suite of scenarios.

--
You received this message because you are subscribed to the Google Groups "Behaviour Driven Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email to behaviordrivendeve...@googlegroups.com.
To post to this group, send email to behaviordriv...@googlegroups.com.
Visit this group at http://groups.google.com/group/behaviordrivendevelopment.
For more options, visit https://groups.google.com/d/optout.



--
------------------------
Andrew Premdas

Jacob G

unread,
Jan 16, 2015, 3:22:27 PM1/16/15
to behaviordriv...@googlegroups.com
While I agree it is useful to have independent scenarios, and I now see that I can build complex scenarios in a more useful way, by doing more than one group of when and then, I am still interested in the answer to my question, although it appears that Behave might have been designed to prevent this (which in itself is an answer)

Thanks,
Jacob

Markus Gaertner

unread,
Jan 16, 2015, 3:45:27 PM1/16/15
to behaviordriv...@googlegroups.com
I have often found that there are things that are stable in the test system among scenarios, i.e. ports in a large billing and rating engine for a telecommunication provider. I usually put these kind of system variables in an environment setting class for my system under test. Then I use Suite Setups, background scenarios or whatever the tool I am using offers me to store that in a publicly accesssible static variable, and can ruse these from my step definitions.

I don't know how to do that in Python, but that's my more general approach to solve that.

Best
Markus

Scaling Agile as if you meant it: http://www.scaledprinciples.org
--
Dipl.-Inform. Markus Gaertner
Author of ATDD by Example - A Practical Guide to Acceptance Test-Driven Development

Liz Keogh

unread,
Jan 17, 2015, 5:22:29 AM1/17/15
to behaviordriv...@googlegroups.com
Tying scenarios together is an anti-pattern for sure, for the reasons Andrew states below.

Sometimes it's worth doing just to be pragmatic, if for instance your set-up of context takes a long time. I recommend only doing this within the same capability and the same feature; the things happening in the scenarios you're combining must be related.

So for instance, you might have something like:

    Given Joe Green has five books worth £25.30 in his basket
    And is ready to pay
    When he chooses "1st Class shipping" at £3.60
    Then the total should be £28.90
    When he chooses "Next Day shipping" at £5.00
    Then the total should be £30.30.

    Given Primula Rich has five books worth £25.30 in her basket
    And a Prime account
    When she goes to pay
    Then she should be told she has Next Day Shipping for free
    And the total should be £25.30.

There are two scenarios tied up in that first one, but they're functionally similar. If your context of putting the books in the basket takes a while then it might be worth doing; sometimes the code necessary to make that context easy to set up isn't worth it. If you do this, recognize the trade-off and be prepared to split them up if you find them failing and can't tell why.

The second, though, is looking at a different capability and a different internal feature, so I'd always keep it separate.

And I wouldn't pass state between scenarios; just make them into one longer scenario as above.

Jacob, in the situation you're talking about, they don't appear to be functionally similar, so I'd keep it separate as Andrew suggests. An alternative might be to consider what valuable thing your scenarios are achieving, which would enable you to have one scenario with several lower-level steps within it. So you might have something like:

    Given <context>
    When I connect to my system <- finds and uses the port number
    Then <outcome>.

Sometimes talking through examples of why things behave that way and what makes it valuable can help you to get around the whole problem in the first place.

Cheers,
Liz.

Jacob G

unread,
Jan 18, 2015, 8:41:58 PM1/18/15
to behaviordriv...@googlegroups.com
I guess the best way to describe my current setup would be:

GIven my system is ready
When I start-up my server
Then I can get the port number

Given my server is started
When I start-up my application
Then I can connect to my application at the port number

So, I can separate out the retrieval of the port number, but the server does need to be started before I can start my application.


Liz Keogh

unread,
Jan 18, 2015, 9:17:36 PM1/18/15
to behaviordriv...@googlegroups.com

I think you may have one of those rare cases in which two "when's" are applicable. I always try to describe scenarios from a user's perspective, but when you have an interaction between two users (where a system interaction or the passing of time may count) then it's sometimes better to model it as two "whens".

    Given my system is ready
    When Ollie Ops starts the server
    And Ursula User starts the app
    Then Ursula should be connected via the right port
    And <she should see the thing she connected for>.

Phrasing it from 3rd person perspective on can help clarify this. You can always make these into 2 scenarios, but if starting the server has no value without connecting the app then I wouldn't bother.

Not all BDD tools support two "when's". I find this very occasionally annoying.

Cheers,
Liz.

Reply all
Reply to author
Forward
0 new messages