Last active
May 12, 2017 07:09
-
-
Save hiroaki-yamamoto/a1f55105fc67b78d20e8e6e640af4968 to your computer and use it in GitHub Desktop.
Useful Template View Test Base Classes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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