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. Template tag - list punctuation for a list of items by shapiromatron 11 months ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months, 1 week ago
  3. Serializer factory with Django Rest Framework by julio 1 year, 6 months ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
  5. Help text hyperlinks by sa2812 1 year, 7 months 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.