Unit tests with Pylons and its XMLRPCController

 · 1 min read
 · Jean Schurger

Now that you have implemented a nice XMLRPCController in your Pylons application, it's time to write unit tests covering it. The problem is that the xmlrpclib tries to make a real HTTP connection to an address, but the TestApp used in your TestController is not a real server, and doesn't listen to any address.

Here is a quick way to enable the coverage of your XMLRPCController. Inspired by Kumar McMillan on this thread.

from StringIO import StringIO
import xmlrpclib
from xmlrpclib import ServerProxy
from mygreatapp.tests import TestController

# a fake httplib.HTTP using 'app' (see TestController.__init__())
class WSGILikeHTTP():
        def __init__(self, host, app):
                self.app = app
                self.headers = {}
                self.content = StringIO()

        def putrequest(self, method, handler):
                self.method = method
                self.handler = handler

        def putheader(self, key, value):
                self.headers[key] = value

        def endheaders(self):
                pass

        def send(self, body):
                self.body = body

        def getfile(self):
                return self.content

        def getreply(self):
                if self.method == "POST":
                        r = self.app.post(self.handler,
                                      headers=self.headers,
                                      params=self.body)
                        self.content = StringIO(r.response)
                return (200, None, None)

class WSGIAppTransport(xmlrpclib.Transport):
        # Only here to pass the 'app'
        def __init__(self, app):
                xmlrpclib.Transport.__init__(self)
                self.app = app

        # return the fake httplib.HTTP(host)
        def make_connection(self, host):
                host, extra_headers, x509 = self.get_host_info(host)
                return WSGILikeHTTP(host, self.app)

class TestApiController(TestController):
        def test_voicemails_update(self):
                # URL _MUST_ starts with 'http' or 'https' (see xmlrpclib.py)
                server = ServerProxy('http://dummy/api',
                                     transport=WSGIAppTransport(self.app))
                server.super_function("Foo", "Bla", 42)