2011-03-06 8 views
9

Estoy desarrollando un servidor twisted.web - consiste en algunos recursos que además de renderizar cosas usan adbapi para buscar algunos datos y escribir algunos datos en la base de datos postgresql. Intento averiguar cómo escribir una prueba unittest de prueba que verifique la representación de recursos sin usar net (en otras palabras: eso inicializaría un recurso, lo generaría una solicitud ficticia, etc.).¿Cómo probar el recurso web retorcido con prueba?

Supongamos que el recurso Ver es una hoja simple que en render_GET devuelve NOT_DONE_YET y juega con adbapi para producir texto simple como resultado. Ahora, he escrito este código inútil y no puedo llegar a hacer lo que realmente iniciar el recurso y producir algún tipo de respuesta sensata:

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) 

La salida es ... 1. También he intentado tal enfoque: salida = request.render (ver) pero el mismo resultado = 1. ¿Por qué? Sería muy agradecido por algunos ejemplo cómo escribir tales unittest!

Respuesta

10

Aquí es una función que hará que una solicitud y convertir el resultado en un diferido que se activa cuando finalice el procesamiento:

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

De hecho, es utilizado en conjunto de pruebas de Twisted Web, pero es privada porque no tiene ninguna unidad de se prueba a sí mismo. ;)

Se puede utilizar para escribir una prueba como esta:

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

Gracias! Parece que funciona, pero retorcido nunca devuelve el resultado - He comprobado con impresión, espera después de request.notify Finish(). La babosa que he probado funciona bien cuando se accede. Qué podría estar mal? – pielgrzym

+0

Se detiene en 'request.setHeader' y request.setHost; lo más probable es que no estén implementados en DummyRequest (o en uno de ellos). – pielgrzym

+0

Sí falla en: setHeader y getCookie - Creo que subclasando a DummyRequest y creando la funcionalidad cookie y setHeader lo resolverá :) – pielgrzym

0

Aquí es una clase DummierRequest que corrige casi todos mis problemas. Lo único que queda es ¡no establece ningún código de respuesta! ¿Por qué?

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

En realidad, establece 404. ¿Es posible que tenga que configurar el código 200 manualmente en mi clase de Recursos? – pielgrzym

+0

'request.setResponseCode()' se suele llamar en los métodos 'ResourceSubclass.render()' o '.processingFailed()'. – jfs

+0

En la función _render() anterior llamamos a request.render(). ¿Podría ser causado por una solicitud usando NOT_DONE_YET & deferreds? – pielgrzym

Cuestiones relacionadas