Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
192 changes: 192 additions & 0 deletions test_plus/status_codes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
class StatusCodeAssertionMixin(object):
"""
The following `assert_http_###_status_name` methods were intentionally added statically instead of dynamically so
that code completion in IDEs like PyCharm would work. It is preferred to use these methods over the response_XXX
methods, which could be deprecated at some point. The assert methods contain both the number and the status name
slug so that people that remember them best by their numeric code and people that remember best by their name will
be able to easily find the assertion they need. This was also directly patterned off of what the `Django Rest
Framework uses <https://github.com/encode/django-rest-framework/blob/master/rest_framework/status.py>`_.
"""

def _assert_http_status(self, status_code, response=None, msg=None, url=None):
response = self._which_response(response)
self.assertEqual(response.status_code, status_code, msg)
if url is not None:
self.assertEqual(response.url, url)

def assert_http_100_continue(self, response=None, msg=None):
self._assert_http_status(100, response=response, msg=msg)

def assert_http_101_switching_protocols(self, response=None, msg=None):
self._assert_http_status(101, response=response, msg=msg)

def assert_http_200_ok(self, response=None, msg=None):
self._assert_http_status(200, response=response, msg=msg)

def assert_http_201_created(self, response=None, msg=None):
self._assert_http_status(201, response=response, msg=msg)

def assert_http_202_accepted(self, response=None, msg=None):
self._assert_http_status(202, response=response, msg=msg)

def assert_http_203_non_authoritative_information(self, response=None, msg=None):
self._assert_http_status(203, response=response, msg=msg)

def assert_http_204_no_content(self, response=None, msg=None):
self._assert_http_status(204, response=response, msg=msg)

def assert_http_205_reset_content(self, response=None, msg=None):
self._assert_http_status(205, response=response, msg=msg)

def assert_http_206_partial_content(self, response=None, msg=None):
self._assert_http_status(206, response=response, msg=msg)

def assert_http_207_multi_status(self, response=None, msg=None):
self._assert_http_status(207, response=response, msg=msg)

def assert_http_208_already_reported(self, response=None, msg=None):
self._assert_http_status(208, response=response, msg=msg)

def assert_http_226_im_used(self, response=None, msg=None):
self._assert_http_status(226, response=response, msg=msg)

def assert_http_300_multiple_choices(self, response=None, msg=None):
self._assert_http_status(300, response=response, msg=msg)

def assert_http_301_moved_permanently(self, response=None, msg=None, url=None):
self._assert_http_status(301, response=response, msg=msg, url=url)

def assert_http_302_found(self, response=None, msg=None, url=None):
self._assert_http_status(302, response=response, msg=msg, url=url)

def assert_http_303_see_other(self, response=None, msg=None):
self._assert_http_status(303, response=response, msg=msg)

def assert_http_304_not_modified(self, response=None, msg=None):
self._assert_http_status(304, response=response, msg=msg)

def assert_http_305_use_proxy(self, response=None, msg=None):
self._assert_http_status(305, response=response, msg=msg)

def assert_http_306_reserved(self, response=None, msg=None):
self._assert_http_status(306, response=response, msg=msg)

def assert_http_307_temporary_redirect(self, response=None, msg=None):
self._assert_http_status(307, response=response, msg=msg)

def assert_http_308_permanent_redirect(self, response=None, msg=None):
self._assert_http_status(308, response=response, msg=msg)

def assert_http_400_bad_request(self, response=None, msg=None):
self._assert_http_status(400, response=response, msg=msg)

def assert_http_401_unauthorized(self, response=None, msg=None):
self._assert_http_status(401, response=response, msg=msg)

def assert_http_402_payment_required(self, response=None, msg=None):
self._assert_http_status(402, response=response, msg=msg)

def assert_http_403_forbidden(self, response=None, msg=None):
self._assert_http_status(403, response=response, msg=msg)

def assert_http_404_not_found(self, response=None, msg=None):
self._assert_http_status(404, response=response, msg=msg)

def assert_http_405_method_not_allowed(self, response=None, msg=None):
self._assert_http_status(405, response=response, msg=msg)

def assert_http_406_not_acceptable(self, response=None, msg=None):
self._assert_http_status(406, response=response, msg=msg)

def assert_http_407_proxy_authentication_required(self, response=None, msg=None):
self._assert_http_status(407, response=response, msg=msg)

def assert_http_408_request_timeout(self, response=None, msg=None):
self._assert_http_status(408, response=response, msg=msg)

def assert_http_409_conflict(self, response=None, msg=None):
self._assert_http_status(409, response=response, msg=msg)

def assert_http_410_gone(self, response=None, msg=None):
self._assert_http_status(410, response=response, msg=msg)

def assert_http_411_length_required(self, response=None, msg=None):
self._assert_http_status(411, response=response, msg=msg)

def assert_http_412_precondition_failed(self, response=None, msg=None):
self._assert_http_status(412, response=response, msg=msg)

def assert_http_413_request_entity_too_large(self, response=None, msg=None):
self._assert_http_status(413, response=response, msg=msg)

def assert_http_414_request_uri_too_long(self, response=None, msg=None):
self._assert_http_status(414, response=response, msg=msg)

def assert_http_415_unsupported_media_type(self, response=None, msg=None):
self._assert_http_status(415, response=response, msg=msg)

def assert_http_416_requested_range_not_satisfiable(self, response=None, msg=None):
self._assert_http_status(416, response=response, msg=msg)

def assert_http_417_expectation_failed(self, response=None, msg=None):
self._assert_http_status(417, response=response, msg=msg)

def assert_http_422_unprocessable_entity(self, response=None, msg=None):
self._assert_http_status(422, response=response, msg=msg)

def assert_http_423_locked(self, response=None, msg=None):
self._assert_http_status(423, response=response, msg=msg)

def assert_http_424_failed_dependency(self, response=None, msg=None):
self._assert_http_status(424, response=response, msg=msg)

def assert_http_426_upgrade_required(self, response=None, msg=None):
self._assert_http_status(426, response=response, msg=msg)

def assert_http_428_precondition_required(self, response=None, msg=None):
self._assert_http_status(428, response=response, msg=msg)

def assert_http_429_too_many_requests(self, response=None, msg=None):
self._assert_http_status(429, response=response, msg=msg)

def assert_http_431_request_header_fields_too_large(self, response=None, msg=None):
self._assert_http_status(431, response=response, msg=msg)

def assert_http_451_unavailable_for_legal_reasons(self, response=None, msg=None):
self._assert_http_status(451, response=response, msg=msg)

def assert_http_500_internal_server_error(self, response=None, msg=None):
self._assert_http_status(500, response=response, msg=msg)

def assert_http_501_not_implemented(self, response=None, msg=None):
self._assert_http_status(501, response=response, msg=msg)

def assert_http_502_bad_gateway(self, response=None, msg=None):
self._assert_http_status(502, response=response, msg=msg)

def assert_http_503_service_unavailable(self, response=None, msg=None):
self._assert_http_status(503, response=response, msg=msg)

def assert_http_504_gateway_timeout(self, response=None, msg=None):
self._assert_http_status(504, response=response, msg=msg)

def assert_http_505_http_version_not_supported(self, response=None, msg=None):
self._assert_http_status(505, response=response, msg=msg)

def assert_http_506_variant_also_negotiates(self, response=None, msg=None):
self._assert_http_status(506, response=response, msg=msg)

def assert_http_507_insufficient_storage(self, response=None, msg=None):
self._assert_http_status(507, response=response, msg=msg)

def assert_http_508_loop_detected(self, response=None, msg=None):
self._assert_http_status(508, response=response, msg=msg)

def assert_http_509_bandwidth_limit_exceeded(self, response=None, msg=None):
self._assert_http_status(509, response=response, msg=msg)

def assert_http_510_not_extended(self, response=None, msg=None):
self._assert_http_status(510, response=response, msg=msg)

def assert_http_511_network_authentication_required(self, response=None, msg=None):
self._assert_http_status(511, response=response, msg=msg)
3 changes: 2 additions & 1 deletion test_plus/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from django.test.utils import CaptureQueriesContext
from django.utils.functional import curry

from test_plus.status_codes import StatusCodeAssertionMixin
from .compat import reverse, NoReverseMatch, get_api_client


Expand Down Expand Up @@ -76,7 +77,7 @@ def __exit__(self, *args):
self.testcase.client.logout()


class BaseTestCase(object):
class BaseTestCase(StatusCodeAssertionMixin):
"""
Django TestCase with helpful additional features
"""
Expand Down
38 changes: 38 additions & 0 deletions test_project/test_app/tests/test_unittests.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import re

import django
import factory
import sys
Expand Down Expand Up @@ -209,6 +211,42 @@ def test_delete_follow(self):
res = self.delete(url, follow=True)
self.assertTrue(res.status_code, 200)

@staticmethod
def _test_http_response(method, response=None, msg=None, url=None):
try:
if url is not None:
method(response=response, msg=msg, url=url)
else:
method(response=response, msg=msg)
except AssertionError as e:
msg = '{method_name}: {error}'.format(method_name=method.__name__, error=e)
e.args = (msg,)
raise

def test_http_status_code_assertions(self):
"""
This test iterates through all the http_###_status_code methods in the StatusCodeAssertionMixin and tests that
they return the correct status code.
"""
from test_plus.status_codes import StatusCodeAssertionMixin
for attr in dir(StatusCodeAssertionMixin):
method = getattr(self, attr, None)
match = re.match(r'[a-z_]+(?P<status_code>[\d]+)[a-z_]+', attr)
if callable(method) is True and match is not None:
status_code = int(match.groupdict()['status_code'])
url = self.reverse('status-code-view', status_code)
res_url = None
res = self.get(url)

if status_code in (301, 302):
res_url = self.reverse('view-200')

# with response
self._test_http_response(method, res, url=res_url)

# without response
self._test_http_response(method, url=res_url)

def test_get_check_200(self):
res = self.get_check_200('view-200')
self.assertTrue(res.status_code, 200)
Expand Down
2 changes: 2 additions & 0 deletions test_project/test_app/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@
view_410, view_contains, view_context_with, view_context_without,
view_headers, view_is_ajax, view_json, view_redirect,
CBLoginRequiredView, CBView,
status_code_view,
)

urlpatterns = [
url(r'^accounts/', include('django.contrib.auth.urls')),
url(r'^status-code-view/(?P<status>[\d]+)/$', status_code_view, name='status-code-view'),
url(r'^view/200/$', view_200, name='view-200'),
url(r'^view/201/$', view_201, name='view-201'),
url(r'^view/204/$', view_204, name='view-204'),
Expand Down
9 changes: 9 additions & 0 deletions test_project/test_app/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@

# Function-based test views

def status_code_view(request, status=200):
status = int(status)
if status in (301, 302):
is_perm = True if status == 301 else False
return redirect('view-200', permanent=is_perm)

return HttpResponse('', status=status)


def view_200(request):
return HttpResponse('', status=200)

Expand Down