Skip to content

Instantly share code, notes, and snippets.

@hiroaki-yamamoto
Last active May 12, 2017 07:09
Show Gist options
  • Save hiroaki-yamamoto/a1f55105fc67b78d20e8e6e640af4968 to your computer and use it in GitHub Desktop.
Save hiroaki-yamamoto/a1f55105fc67b78d20e8e6e640af4968 to your computer and use it in GitHub Desktop.
Useful Template View Test Base Classes
#!/usr/bin/env python
# coding=utf-8
"""View test base."""
from urllib import parse
from django.conf import settings
from django.contrib.auth import authenticate, get_user_model, get_user
from django.core.urlresolvers import reverse, resolve
from django.http import HttpResponseRedirect
from django.test import Client, RequestFactory
from django.urls import NoReverseMatch
from django.views.generic import TemplateView
class UserBase(object):
"""
UserBase.
The test case inherit this class has self.user.
The value can be changed by setting user parameter.
"""
def __init__(self, *args, **kwargs):
"""Init."""
super(UserBase, self).__init__(*args, **kwargs)
self.authenticate = authenticate
def setUp(self, *args, **kwargs):
"""Init."""
super(UserBase, self).setUp(*args, **kwargs)
self.user_password = "test"
self.user_email = "test@example.com"
self.user = kwargs.pop("user", get_user_model().objects.create_user(
username=self.user_email, email=self.user_email,
password=self.user_password
))
class UserLoggedIn(object):
"""User login situation."""
def setUp(self):
"""Setup."""
if not isinstance(self, UserBase):
raise TypeError("Inherit base.UserBase class")
if not isinstance(self, URLAssignmentTestBase):
raise TypeError(
self, "Inherit base.URLAssignmentTestBase class"
)
super(UserLoggedIn, self).setUp()
self.client.login(
username=self.user_email,
password=self.user_password
)
class URLAssignmentTestBase(object):
"""
URL assignment test base.
Required/optional attribute:
endpoint (required): The endpoint. e.g. home:index
page_url (required): The url associated with the endpoint. e.g. /
url_kwargs: Any keyword arguments to be put to reverse function.
url_args: Any arguments to be put to reverse function.
status_code: Expected Status Code. 200 by default.
"""
method = "get"
url_kwargs = {}
url_args = []
status_code = 200
def __init__(self, *args, **kwargs):
"""Setup."""
self.client = Client()
if not getattr(self, "cli_kwargs", None):
self.cli_kwargs = {}
if not getattr(self, "view", None):
self.view = self.view_cls.as_view()
super(URLAssignmentTestBase, self).__init__(*args, **kwargs)
def make_request(self):
"""Make a raw request from RequestFactory."""
request = getattr(RequestFactory(), self.method)(
self.page_url, **self.cli_kwargs
)
request.session = self.client.session
request.user = get_user(request)
return request
def set_client_kwargs(self, **kwargs):
"""Set Client args."""
self.cli_kwargs.update(kwargs)
def make_call(self):
"""Push a request the the view and return the resp from the view."""
return getattr(self.client, self.method.lower())(
self.page_url, **self.cli_kwargs
)
def test_url(self):
"""The URL should be found in the app."""
self.assertEqual(
reverse(
self.endpoint, args=self.url_args, kwargs=self.url_kwargs
), self.page_url
)
def test_assignment(self):
"""The view should be assigned to URL."""
self.assertEqual(
resolve(self.page_url).func.__name__, self.view.__name__
)
def test_method(self):
"""The view should return 200."""
ret = self.make_call()
self.assertEqual(
ret.status_code, self.status_code,
("Code: {}, Content: {}").format(
ret.status_code, ret.content or getattr(ret, "url", '')
)
)
return ret
class TemplateViewTestBase(URLAssignmentTestBase):
"""
View test base.
Required/optional attribute:
template_name (required): The file name of the template file.
content_type (optional): The type of content as MimeType. By default,
this is set to text/html.
view_cls (required): The view class.
endpoint (required): The endpoint. e.g. home:index
page_url (required): The url associated with the endpoint. e.g. /
"""
method = "get"
def test_class(self):
"""The view class should be a subclass of TemplateView."""
self.assertTrue(issubclass(self.view_cls, TemplateView))
def test_template_name(self):
"""The TemplateView should have proper template name."""
self.assertEqual(self.view_cls.template_name, self.template_name)
def test_content_type(self):
"""The content type should be expected."""
self.assertEqual(
self.view_cls.content_type,
getattr(self, "content_type", None)
)
class LoginRedirectBase(object):
"""Specify the response should RedirectResponse to login page."""
def test_method(self):
"""The returned response should be redirect response."""
resp = self.make_call()
self.assertIsInstance(resp, HttpResponseRedirect)
self.assertEqual(
resp.url,
reverse("user:login") + ("?next={}").format(self.page_url)
)
class NotLoginRedirectBase(object):
"""Specify the response should redirect Response to the next page."""
def test_method(self):
"""The returned response should be redirect response."""
next_url = parse.parse_qs(parse.urlparse(self.page_url).query).get(
"next", settings.LOGIN_REDIRECT_URL
)
try:
next_url = reverse(next_url)
except NoReverseMatch:
pass
resp = self.make_call()
self.assertIsInstance(resp, HttpResponseRedirect)
self.assertEqual(resp.url, next_url)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment