I have a web application that uses session data to determine what to do next. The application is running in the browser and does what it shall do. I'd like to write an automated test to have that knowledge for future projects. The last hours I failed miserable to initialize (and hand over) session data within my test. Also I couldn't find the answer for such a basic case on the web.
However, here is the app code:
import web
from project import code
urls = (
"/page", "/Page",
"/", "Index"
)
app = web.application(urls, globals())
# Little hack so that debug mode works with sessions.
if web.config.get('_session') is None:
store = web.session.DiskStore('sessions')
session = web.session.Session(app, store, initializer={'data':None})
web.config._session = session
else:
session = web.config._session
render = web.template.render('templates/', base="layout")
class Index():
def GET(self):
# This is used to "setup" the session with starting values.
# code.START contains a dict "whatnext"
# that assigns keywords to information what to do next.
# It also contains a attribute "name"
session.data = code.START
web.seeother("/page")
class Page(object):
def GET(self):
if session.data:
return render.page(data=session.data)
else:
# This is here in case someone puts "/page" directly as URL.
# wrong_page just has a link to "/" and everything will be fine
# from there on.
return render.wrong_page()
def POST(self):
form = web.input(action=None)
if form.action in session.data.whatnext:
# The method .go returns what to do next according to the
# keywords.
session.data = session.data.go(form.action)
web.seeother("/page")
if __name__ == "__main__":
app.run()
The code itself is not the scope of the question, but I can provide it, if necessary.
However, page.html looks like this
$def with (data)
Something something dependend on the data.
$if data.name == "finished":
<p><a href="/"> Again? </a></p>
$else:
<p>
<form action="/page" method="POST">
<input type="text" name="action"> <input type="SUBMIT">
</form>
</p>
In the test the following is used:
from nose.tools import *
import re
def assert_response(resp, contains=None, status="200"):
assert status in resp.status, "Excpected response %r not in %r" % (status,
resp.status)
if status == "200":
assert resp.data, "Response data is empty."
if contains:
assert contains in resp.data, "Response does not contain %r" % contains
and here is the actual test:
from nose.tools import *
from bin.app import app # the code above
from tests.tools import assert_response
def test_redirect():
# Check that we get a 303 on the / URL
resp = app.request("/")
assert_response(resp, status="303")
def test_wrong_page():
# test the first GET request to /game
resp = app.request("/page")
assert_response(resp, contains="Go here instead")
def test_page
# test that we get expected values
what_to_do = {'action' : 'foo'}
resp = app.request("/page", method="POST", data=what_to_do)
assert_response(resp, contains="something specific according to foo")
The first two tests work as expected. The third test is not working and I think it is because /page requires session.data to function.
I am getting as ouptut:
Traceback (most recent call last):
File "/.../nose/case.py", line 197, in runTest
self.test(*self.arg)
File "/.../tests/app_tests.py", line 19, in test_page
assert_response(resp, contains="something specific according to foo")
File "/.../tests/tools.py", line 17, in assert_response
resp.status)
AssertionError: Excpected response '200' not in '500 Internal Server Error'
Since I don't know how to initialize the session/session data in the test, my question is: how can I do that, that the automated test can run with the give session information.
You don't need to initialise session in your test, since when you make app.request() call, your app will auto init session for you. The issue here is you don't maintain session id in your test ( your test is like a client as any browser ).
The solution is that when you make first app.request(), record the session id in the response headers. Then supply with the session id when you make subsequent app.request()
Here is my code:
First I make a helper function in tests/tools.py to extract the session id from response header:
then write test as: