|
import json |
|
import urllib |
|
import urlparse |
|
|
|
from django.conf import settings |
|
from django.test import TestCase |
|
from django.core.urlresolvers import reverse |
|
from django.test.client import Client as DjangoClient |
|
|
|
from . import factories as f |
|
|
|
class MyAppTestCase(DjangoTestCase): |
|
class SETTINGS_BASE: |
|
UNDER_TEST = True |
|
AUTHENTICATION_BACKENDS = [ |
|
"akindi.testing.auth_backends.TestcaseUserBackend", |
|
] + settings.AUTHENTICATION_BACKENDS |
|
|
|
class SETTINGS: |
|
# Suclassess can define a SETTINGS attribute with custom settings |
|
pass |
|
|
|
def __init__(self, *args, **kwargs): |
|
self.init_helpers() |
|
super(AkindiTestCase, self).__init__(*args, **kwargs) |
|
self.client = Client(self) |
|
|
|
def setUp(self): |
|
super(AkindiTestCase, self).setUp() |
|
self._old_settings = dict(settings.__dict__) |
|
settings_overrides = ( |
|
self.SETTINGS_BASE.__dict__.items() + |
|
self.get_helper_settings().items() + |
|
self.SETTINGS.__dict__.items() |
|
) |
|
for name, val in settings_overrides: |
|
setattr(settings, name, val) |
|
self.setup_() |
|
|
|
def tearDown(self): |
|
super(AkindiTestCase, self).setUp() |
|
for name, val in self._old_settings.items(): |
|
setattr(settings, name, val) |
|
self.teardown_() |
|
|
|
def teardown_helpers(self): |
|
for helper in reversed(self._helpers): |
|
helper.teardown() |
|
|
|
def teardown_(self): |
|
# Subclasses can override this without calling super() |
|
pass |
|
|
|
def setup_(self): |
|
# Subclasses can override this without calling super() |
|
pass |
|
|
|
# |
|
# Utility methods |
|
# |
|
|
|
def assertRespOk(self, resp): |
|
self.assertGreaterEqual(resp.status_code, 200) |
|
if resp.status_code >= 300: |
|
if resp.status_code <= 399: |
|
raise AssertionError("%s is not <= 299 (location: %s)" |
|
%(resp.status_code, resp.get("location"))) |
|
raise AssertionError("%s is not <= 300 (content: %r)" %( |
|
resp.status_code, resp.content, |
|
)) |
|
|
|
def assertRedirect(self, resp, location): |
|
assert resp.status_code in [301, 302], \ |
|
"Bad status code: %r (not a redirect; content: %r)" %( |
|
resp.status_code, resp.content |
|
) |
|
actual_location = resp.get("location") |
|
assert actual_location, "No Location header" |
|
if location.startswith("/"): |
|
split = urlparse.urlsplit(resp["location"]) |
|
actual_location = urlparse.urlunsplit(('', '') + split[2:]) |
|
self.assertEqual(location, actual_location) |
|
|
|
def reverse(self, *args, **kwargs): |
|
get = kwargs.pop("get", None) |
|
url = reverse(*args, **kwargs) |
|
if get: |
|
url += "?" + urllib.urlencode(get) |
|
return url |
|
|
|
def assertRespNotOk(self, resp, content=None, status=None): |
|
if resp.content == "DAJAXICE_EXCEPTION": |
|
return |
|
if status is not None: |
|
self.assertEqual(resp.status_code, status, 'status %r != %r (content: %r)' %( |
|
resp.status_code, status, resp.content, |
|
)) |
|
elif resp.status_code <= 299: |
|
raise AssertionError('unexpected good status code: %r (content: %r)' |
|
%(resp.status_code, resp.content)) |
|
if content is not None: |
|
self.assertIn(content, resp.content) |
|
|
|
|
|
|
|
class Client(DjangoClient): |
|
def __init__(self, testcase): |
|
self.testcase = testcase |
|
super(Client, self).__init__() |
|
|
|
def set_options(self, options): |
|
self.defaults.update(options) |
|
|
|
def login(self, user=None): |
|
user = user or f.UserFactory() |
|
self.user = user |
|
res = super(Client, self).login(testcase_user=user) |
|
if not res: |
|
raise AssertionError("Could not login as %r" %(user, )) |
|
|
|
def _verb_handler(self, verb, *args, **kwargs): |
|
assertOk = kwargs.pop("assertOk", False) |
|
resp = getattr(DjangoClient, verb)(self, *args, **kwargs) |
|
if assertOk: |
|
self.testcase.assertRespOk(resp) |
|
if "json" in resp.get("content-type", ""): |
|
resp.json = json.loads(resp.content) |
|
else: |
|
resp.json = None |
|
return resp |
|
|
|
def _verb_wrapper(verb): |
|
def _verb_wrapper_helper(self, *args, **kwargs): |
|
return self._verb_handler(verb, *args, **kwargs) |
|
_verb_wrapper_helper.__name__ = verb |
|
return _verb_wrapper_helper |
|
|
|
get = _verb_wrapper("get") |
|
post = _verb_wrapper("post") |
|
head = _verb_wrapper("head") |
|
put = _verb_wrapper("put") |
|
options = _verb_wrapper("options") |
|
delete = _verb_wrapper("delete") |