2014-12-03 106 views
1

我有一個Web應用程序,它使用會話數據來確定下一步該做什麼。 該應用程序正在瀏覽器中運行,並執行它應該做的事情。 我想編寫一個自動化測試,以獲得未來項目的知識。 在我的測試中,最後幾小時我失敗了初始化(和交付)會話數據。此外,我無法找到網絡上這種基本案例的答案。如何在自動化測試中初始化會話數據? (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()調用時,您的應用程序將爲您自動初始化會話。這裏的問題是你沒有在你的測試中維護會話ID(你的測試就像任何瀏覽器的客戶端一樣)。

解決方法是,當您創建第一個app.request()時,將會話標識記錄在響應標頭中。隨後與會話ID提供當你進行後續app.request()

這裏是我的代碼:

首先是讓在測試中一個輔助函數/ tools.py從響應報頭中的會話ID:

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