Search code examples
pythontwistedtrial

How to test twisted web resource with trial?


I'm developing a twisted.web server - it consists of some resources that apart from rendering stuff use adbapi to fetch some data and write some data to postgresql database. I'm trying to figoure out how to write a trial unittest that would test resource rendering without using net (in other words: that would initialize a resource, produce it a dummy request etc.).

Lets assume the View resource is a simple leaf that in render_GET returns NOT_DONE_YET and tinkers with adbapi to produce simple text as a result. Now, I've written this useless code and I can't come up how to make it actually initialize the resource and produce some sensible response:

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)

The output is... 1. I've also tried such approach: output = request.render(view) but same output = 1. Why? I'd be very gratefull for some example how to write such unittest!


Solution

  • Here's a function that will render a request and convert the result into a Deferred that fires when rendering is complete:

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

    It's actually used in Twisted Web's test suite, but it's private because it has no unit tests itself. ;)

    You can use it to write a test like this:

    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