Login

External service Test Client

Author:
theju
Posted:
March 4, 2010
Language:
Python
Version:
1.1
Score:
1 (after 1 ratings)

The inbuilt test client can be used to only test single domain applications ie no support for supplying absolute URLs.

But there are cases where one might like to test against URL rewrites, external domains/services like OpenID, OAuth etc.

This client has an external dependency on httplib2, to maintain the sessions (cookie-based). The API is exactly similar to the inbuilt test client.

>>> from client import TestClient
>>> c = TestClient()
>>> resp = c.get("http://www.google.com/")
>>> resp.status_code
200

Note: Unlike the built-in test client, this test client cannot access the template and context attributes from the response even if testing a local application.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import httplib2
from django.http import HttpResponse, HttpResponseRedirect, parse_cookie
from django.test.client import *

class TestHandler(BaseHandler):
    def __call__(self, environ):
        from django.core import signals

        if self._request_middleware is None:
            self.load_middleware()

        signals.request_started.send(sender=self.__class__)
        try:
            headers = {'Content-type': 'application/x-www-form-urlencoded'}
            http = httplib2.Http()
            request = WSGIRequest(environ)
            if request.COOKIES:
                headers.update({'Cookie': environ['HTTP_COOKIE']})
            request_body = getattr(request, request.method)
            resp, content = http.request(request.META["PATH_INFO"],
                                         method=request.method,
                                         body=request_body.urlencode(),
                                         headers=headers)
            if resp.status in [301, 302, 303, 307]:
                response = HttpResponseRedirect(resp['location'])
            else:
                response = HttpResponse(content=content,
                                        mimetype=None,
                                        status=resp.status,
                                        content_type=resp['content-type'])
            if resp.get('set-cookie'):
                for (key, val) in parse_cookie(resp['set-cookie']).items():
                    response.set_cookie(key, val)

            for middleware_method in self._response_middleware:
                response = middleware_method(request, response)
            response = self.apply_response_fixes(request, response)
        finally:
            signals.request_finished.disconnect(close_connection)
            signals.request_finished.send(sender=self.__class__)
            signals.request_finished.connect(close_connection)
        return response

class TestClient(Client):
    def __init__(self, **defaults):
        super(TestClient, self).__init__(**defaults)
        self.handler = TestHandler()

    def _handle_redirects(self, response):
        response.redirect_chain = []
        while response.status_code in (301, 302, 303, 307):
            url = response['Location']
            scheme, netloc, path, query, fragment = urlsplit(url)

            redirect_chain = response.redirect_chain
            redirect_chain.append((url, response.status_code))

            response = self.get(url, QueryDict(query), follow=False)
            response.redirect_chain = redirect_chain

            if response.redirect_chain[-1] in response.redirect_chain[0:-1]:
                break
        return response

    def get(self, path, data={}, follow=False, **extra):
        extra.update({'PATH_INFO': path})
        return super(TestClient, self).get(path, data=data, follow=follow, **extra)

    def post(self, path, data={}, content_type=MULTIPART_CONTENT, follow=False, **extra):
        extra.update({'PATH_INFO': path})
        return super(TestClient, self).post(path, data=data, content_type=content_type, follow=follow, **extra)

    def put(self, path, data={}, content_type=MULTIPART_CONTENT, follow=False, **extra):
        extra.update({'PATH_INFO': path})
        return super(TestClient, self).put(path, data=data, content_type=content_type, follow=follow, **extra)

    def head(self, path, data={}, follow=False, **extra):
        extra.update({'PATH_INFO': path})
        return super(TestClient, self).head(path, data=data, follow=follow, **extra)

    def options(self, path, data={}, follow=False, **extra):
        extra.update({'PATH_INFO': path})
        return super(TestClient, self).options(path, data=data, follow=follow, **extra)

    def delete(self, path, follow=False, **extra):
        extra.update({'PATH_INFO': path})
        return super(TestClient, self).delete(path, follow=follow, **extra)

More like this

  1. "Magic Link" Management Command by webology 4 months, 1 week ago
  2. Closest ORM models to a latitude/longitude point by simonw 4 months, 1 week ago
  3. Log the time taken to execute each DB query by kennyx46 4 months, 1 week ago
  4. django database snippet by ItsRLuo 4 months, 2 weeks ago
  5. Serialize a model instance by chriswedgwood 5 months, 2 weeks ago

Comments

jjlorenzo (on May 28, 2010):

Django and his community are amazing. This is exactly what I'am looking for.

#

Please login first before commenting.