I'm using Flask and behave
, following the instructions here.
I'm accessing pages using the Flask test client (rather than through a browser via something like Selenium). For example, calling get
on the test client to get a response.
I'd like to access Flask session data in my steps. There are various techniques documented on the Testing Flask Applications page about accessing context and sessions, but I can't see that any of them are quite what I need when using behave, in particular as I'll be accessing the page in one step and then wanting to retrieve session in another.
My environment.py
looks like this:
from my_app import app
def before_scenario(context, scenario):
app.testing = True
# load the test config to ensure e.g. right database used
app.config.from_object('parameters.test')
context.client = app.test_client()
def after_scenario(context, scenario):
pass
The Flask testing technique that came closest to what I needed was this one:
with app.test_client() as c:
rv = c.get('/')
assert flask.session['foo'] == 42
The problem I had with this is that I needed to make the get
request in one step and check the session later in another - i.e. the code was in different functions, so couldn't all be wrapped in the with
block.
Reading sessions
The with statement is essentially syntactic sugar for a pattern similar to try/finally (see link), so I could break this down a bit, giving me the following environment.py
:
from my_app import app
def before_scenario(context, scenario):
# all the code I had before still here
# ...
# and this new line:
context.client.__enter__()
def after_scenario(context, scenario):
# the exit code doesn't actually use its parameters, so providing None is fine
context.client.__exit__(None, None, None)
In my steps, I can now do from flask import session
and access session
as I would in my normal application. You can access request
in the same way.
Writing sessions
As the Flask testing page says, this approach "does not make it possible to also modify the session or to access the session before a request was fired."
If you need to do that, you need to extend the pattern slightly further. First (in before_scenario
), assign the return value from __enter__()
to a variable you can access later:
context.session = context.client.__enter__()
then, in your steps, you can do this:
with context.session.session_transaction() as sess:
sess['key here'] = some_value
This is the second pattern described in the section linked to at the start of my answer. The only modification is that you need to store the return value from __enter__()
since you're not using a with
statement.