Add tests for caching of GET/HEAD requests using

Django's built in caching framework.
Currently fails as some attributes on the Response
object are not pickable
This commit is contained in:
Jacob Magnusson 2012-11-04 12:47:46 +01:00
parent 746686b065
commit 44f280c3ab
2 changed files with 94 additions and 0 deletions

View File

@ -21,6 +21,12 @@ DATABASES = {
} }
} }
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
}
}
# Local time zone for this installation. Choices can be found here: # Local time zone for this installation. Choices can be found here:
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
# although not all choices may be available on all operating systems. # although not all choices may be available on all operating systems.

View File

@ -1,6 +1,8 @@
import pickle
import re import re
from django.conf.urls.defaults import patterns, url, include from django.conf.urls.defaults import patterns, url, include
from django.core.cache import cache
from django.test import TestCase from django.test import TestCase
from django.test.client import RequestFactory from django.test.client import RequestFactory
@ -83,6 +85,7 @@ class HTMLView1(APIView):
urlpatterns = patterns('', urlpatterns = patterns('',
url(r'^.*\.(?P<format>.+)$', MockView.as_view(renderer_classes=[RendererA, RendererB])), url(r'^.*\.(?P<format>.+)$', MockView.as_view(renderer_classes=[RendererA, RendererB])),
url(r'^$', MockView.as_view(renderer_classes=[RendererA, RendererB])), url(r'^$', MockView.as_view(renderer_classes=[RendererA, RendererB])),
url(r'^cache$', MockGETView.as_view()),
url(r'^jsonp/jsonrenderer$', MockGETView.as_view(renderer_classes=[JSONRenderer, JSONPRenderer])), url(r'^jsonp/jsonrenderer$', MockGETView.as_view(renderer_classes=[JSONRenderer, JSONPRenderer])),
url(r'^jsonp/nojsonrenderer$', MockGETView.as_view(renderer_classes=[JSONPRenderer])), url(r'^jsonp/nojsonrenderer$', MockGETView.as_view(renderer_classes=[JSONPRenderer])),
url(r'^html$', HTMLView.as_view()), url(r'^html$', HTMLView.as_view()),
@ -416,3 +419,88 @@ class XMLRendererTestCase(TestCase):
self.assertTrue(xml.startswith('<?xml version="1.0" encoding="utf-8"?>\n<root>')) self.assertTrue(xml.startswith('<?xml version="1.0" encoding="utf-8"?>\n<root>'))
self.assertTrue(xml.endswith('</root>')) self.assertTrue(xml.endswith('</root>'))
self.assertTrue(string in xml, '%r not in %r' % (string, xml)) self.assertTrue(string in xml, '%r not in %r' % (string, xml))
# Tests for caching issue, #346
class CacheRenderTest(TestCase):
"""
Tests specific to caching responses
"""
urls = 'rest_framework.tests.renderers'
cache_key = 'just_a_cache_key'
@classmethod
def _get_pickling_errors(cls, obj, seen=None):
""" Return any errors that would be raised if `obj' is pickled
Courtesy of koffie @ http://stackoverflow.com/a/7218986/109897
"""
if seen == None:
seen = []
try:
state = obj.__getstate__()
except AttributeError:
return
if state == None:
return
if isinstance(state,tuple):
if not isinstance(state[0],dict):
state=state[1]
else:
state=state[0].update(state[1])
result = {}
for i in state:
try:
pickle.dumps(state[i],protocol=2)
except pickle.PicklingError:
if not state[i] in seen:
seen.append(state[i])
result[i] = cls._get_pickling_errors(state[i],seen)
return result
def http_resp(self, http_method, url):
"""
Simple wrapper for Client http requests
Removes the `client' attribute from the response as an instance
of `django.test.client.Client' is not pickable
"""
method = getattr(self.client, http_method)
resp = method(url)
del resp.client
return resp
def test_obj_pickling(self):
"""
Test that responses are properly pickled
"""
resp = self.http_resp('get', '/cache')
# Make sure that no pickling errors occurred
self.assertEqual(self._get_pickling_errors(resp), {})
# Unfortunately LocMem backend doesn't raise PickleErrors but returns
# None instead.
cache.set(self.cache_key, resp)
self.assertTrue(cache.get(self.cache_key) is not None)
def test_head_caching(self):
"""
Test caching of HEAD requests
"""
resp = self.http_resp('head', '/cache')
cache.set(self.cache_key, resp)
cached_resp = cache.get(self.cache_key)
self.assertIsInstance(cached_resp, Response)
def test_get_caching(self):
"""
Test caching of GET requests
"""
resp = self.http_resp('get', '/cache')
cache.set(self.cache_key, resp)
cached_resp = cache.get(self.cache_key)
self.assertIsInstance(cached_resp, Response)
self.assertEqual(cached_resp.content, resp.content)