2014-12-03 8 views
1

У меня есть веб-приложение, которое использует данные сеанса, чтобы определить, что делать дальше. Приложение работает в браузере и делает то, что он должен делать. Я хотел бы написать автоматизированный тест, чтобы иметь эти знания для будущих проектов. В последние часы я потерпел неудачу, чтобы инициализировать (и передать) данные сеанса в рамках моего теста. Также я не мог найти ответ на такой базовый случай в Интернете.Как инициализировать данные сеанса в автоматическом тесте? (python 2.7, webpy, nosetests)

Однако здесь код приложения:

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() 

Сам код не сфера вопроса, но я могу представить его, если это необходимо.

Однако page.html выглядит следующим образом

$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> 

В тесте используется следующее:

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 

и вот сам тест:

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") 

Первый два теста работают так, как ожидалось. Третий тест не работает, и я думаю, что это потому, что/page требует функции session.data.

Я получаю в 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' 

Поскольку я не знаю, как инициализировать данные сеанса/сеансов в тесте, мой вопрос: как я могу это сделать, что автоматизированный тест может запустить с информацией о сеансе передачи.

ответ

1

Вам не нужно инициализировать сеанс в своем тесте, поскольку, когда вы совершаете вызов app.request(), ваше приложение будет автоматически запускать сеанс для вас. Проблема здесь заключается в том, что вы не сохраняете идентификатор сеанса в своем тесте (ваш тест похож на клиента как на любого браузера).

Решение состоит в том, что при первом создании app.request() записывайте идентификатор сеанса в заголовках ответов. Затем поставить с идентификатором сессии, когда вы делаете последующий app.request()

Вот мой код:

Сначала я сделать вспомогательную функцию в тестах/tools.py извлечь идентификатор сеанса из заголовка ответа:

def get_session_id(resp): 
    cookies_str = resp.headers['Set-Cookie'] 
    if cookies_str: 
     for kv in cookies_str.split(';'): 
      if 'webpy_session_id=' in kv: 
       return kv 

затем написать тест, как:

def test_session(): 
    resp = app.request('/') 
    session_id = get_session_id(resp) 

    resp1 = app.request('/game', headers={'Cookie':session_id}) 
    assert_response(resp1, status='200', contains='Central Corridor')