2011-03-06 55 views
9

我正在開發一個twisted.web服務器 - 它包括一些資源,除了渲染的東西用adbapi獲取一些數據,並寫一些數據到PostgreSQL數據庫的。我想figoure如何寫一個單元測試試驗將測試資源的渲染,而無需使用網(換句話說:這將初始化資源,生產它的虛擬要求等)。如何使用試用測試扭曲的網頁資源?

讓我們假設View資源是一個簡單的葉子,它在render_GET中返回NOT_DONE_YET和帶有adbapi的tinkers來產生簡單的文本。現在,我已經寫了這個無用的代碼,我不能想出如何使它真正初始化的資源和產生一些合理的反應:

from twisted.trial import unittest 
from myserv.views import View 
from twisted.web.test.test_web import DummyRequest 

class ExistingView(unittest.TestCase): 
    def test_rendering(self): 
     slug = "hello_world" 
     view = View(slug) 
     request = DummyRequest(['']) 
     output = view.render_GET(request) 
     self.assertEqual(request.responseCode, 200) 

輸出是... 1.我也試過這種方法:output = request.render(view)但輸出相同= 1。爲什麼?我會非常 gratefull一些例如如何寫這樣的單元測試!

回答

10

這裏將呈現一個請求,並將結果轉換成一個功能的延期是在渲染時大火已完成:

def _render(resource, request): 
    result = resource.render(request) 
    if isinstance(result, str): 
     request.write(result) 
     request.finish() 
     return succeed(None) 
    elif result is server.NOT_DONE_YET: 
     if request.finished: 
      return succeed(None) 
     else: 
      return request.notifyFinish() 
    else: 
     raise ValueError("Unexpected return value: %r" % (result,)) 

它實際上是在扭曲的網絡的測試套件使用,但它是私有的,因爲它沒有單位測試自己。 ;)

你可以用它來寫一個測試是這樣的:

def test_rendering(self): 
    slug = "hello_world" 
    view = View(slug) 
    request = DummyRequest(['']) 
    d = _render(view, request) 
    def rendered(ignored): 
     self.assertEquals(request.responseCode, 200) 
     self.assertEquals("".join(request.written), "...") 
     ... 
    d.addCallback(rendered) 
    return d 
+0

謝謝!它似乎工作,但扭曲永不返回結果 - 我檢查了打印,它在request.notifyFinish()後等待。我測試過的slu works在訪問時效果很好。什麼可能是錯的? – pielgrzym 2011-03-06 20:32:31

+0

它停止對「request.setHeader」和request.setHost - 最有可能他們不是在DummyRequest實現(或其中一人)。 – pielgrzym 2011-03-06 20:39:14

+0

燁失敗的:和的setHeader的getCookie - 我想繼承DummyRequest和創建的cookie和功能的setHeader會解決這個:) – pielgrzym 2011-03-06 21:02:19

0

這裏是一個DummierRequest類,修復幾乎所有的問題。唯一剩下的就是它不設置任何響應代碼!爲什麼?

from twisted.web.test.test_web import DummyRequest 
from twisted.web import server 
from twisted.internet.defer import succeed 
from twisted.internet import interfaces, reactor, protocol, address 
from twisted.web.http_headers import _DictHeaders, Headers 

class DummierRequest(DummyRequest): 
    def __init__(self, postpath, session=None): 
     DummyRequest.__init__(self, postpath, session) 
     self.notifications = [] 
     self.received_cookies = {} 
     self.requestHeaders = Headers() 
     self.responseHeaders = Headers() 
     self.cookies = [] # outgoing cookies 

    def setHost(self, host, port, ssl=0): 
     self._forceSSL = ssl 
     self.requestHeaders.setRawHeaders("host", [host]) 
     self.host = address.IPv4Address("TCP", host, port) 

    def addCookie(self, k, v, expires=None, domain=None, path=None, max_age=None, comment=None, secure=None): 
     """ 
     Set an outgoing HTTP cookie. 

     In general, you should consider using sessions instead of cookies, see 
     L{twisted.web.server.Request.getSession} and the 
     L{twisted.web.server.Session} class for details. 
     """ 
     cookie = '%s=%s' % (k, v) 
     if expires is not None: 
      cookie = cookie +"; Expires=%s" % expires 
     if domain is not None: 
      cookie = cookie +"; Domain=%s" % domain 
     if path is not None: 
      cookie = cookie +"; Path=%s" % path 
     if max_age is not None: 
      cookie = cookie +"; Max-Age=%s" % max_age 
     if comment is not None: 
      cookie = cookie +"; Comment=%s" % comment 
     if secure: 
      cookie = cookie +"; Secure" 
     self.cookies.append(cookie) 

    def getCookie(self, key): 
     """ 
     Get a cookie that was sent from the network. 
     """ 
     return self.received_cookies.get(key) 

    def getClientIP(self): 
     """ 
     Return the IPv4 address of the client which made this request, if there 
     is one, otherwise C{None}. 
     """ 
     return "192.168.1.199" 
+0

它實際上並設置404是否有可能,我要在我的資源類手動設置代碼200? – pielgrzym 2011-03-07 11:53:04

+0

'request.setResponseCode()'通常被稱爲在'ResourceSubclass.render()'或'.processingFailed()'方法。 – jfs 2011-03-08 21:38:39

+0

在_render()函數上面我們稱之爲request.render()。可能是由於使用NOT_DONE_YET&deferreds的請求導致的? – pielgrzym 2011-03-12 19:47:28