Testhelpers — Makes it easier to write tests for your cradmin views

Test case mixins

class MockRequestResponse(response, request)

Bases: object

Return type of TestCaseMixin.mock_request(), TestCaseMixin.mock_http200_getrequest_htmls() and TestCaseMixin.mock_postrequest().

response

The HttpResponse object.

request

The RequestFactory-generated HttpRequest object.

selector

A htmls.S object created with the entire content of the response as input. Only available when using TestCaseMixin.mock_http200_getrequest_htmls().

class AbstractTestCaseMixin

Bases: object

Implements the common API for the test case mixins.

viewclass = None

The view class - must be set in subclasses unless you override get_viewclass().

get_viewclass()

Get the view class. Defaults to viewclass

make_view()

Make view function.

Calls get_viewclass().as_view() by default.

get_requestfactory_class()

Get the request factory class.

Must be implemented in subclasses.

create_default_user_for_mock_request()

Create default user for mock request.

Defaults to returning mommy.make(settings.AUTH_USER_MODEL), which should create a user no matter what user model you are using, unless you do something very complex for users.

You can override this if you want to change the default properties of users for all tests in this testcase, but it is normally better to just use the requestuser kwarg for mock_request() (or any of the more specialized mock_*request(..) methods)

Must return a user object compatible with django.http.HttpRequest.user. This means that the method can also return an AnonymousUser, but if you need this you should use NoLoginTestCaseMixin (which just overrides this method).

make_minimal_request(method, requestkwargs=None, httpheaders=None)

Make a minimal request object.

Parameters:
  • method (str) – The http method (get, post, …).
  • requestkwargs (dict) – Kwargs for the request. Defaults to {'path': '/'}, and the path is added unless it is included in the dict. The data you can include in this dict is the same as for the get, post, … methods on django.test.Client (depends on the method kwarg).
  • httpheaders (dict) – Extra http headers needed.
Returns:

The created request object.

prettyformat_response_content(response)

Must be implemented in subclasses.

mock_request(method, cradmin_role=None, cradmin_app=None, cradmin_instance=None, requestuser=None, messagesmock=None, sessionmock=None, requestattributes=None, httpheaders=None, requestkwargs=None, viewkwargs=None, expected_statuscode=None, htmls_selector=False, verbose=False)

Create a mocked request using make_requestfactory() and mock.MagicMock.

Parameters:
  • method – The http method (get, post, …).
  • httpheaders (httpheaders) – Forwarded to make_minimal_request(). Extra HTTP headers to be added to request.META.
  • requestkwargs (dict) – Forwarded to make_minimal_request().
  • cradmin_role – The request.cradmin_role to use. Defaults to mock.MagicMock().
  • cradmin_app – The request.cradmin_app to use. Defaults to mock.MagicMock().
  • cradmin_instance – The request.cradmin_instance to use. Defaults to mock.MagicMock().
  • requestuser – The request.requestuser to use. Defaults to mock.MagicMock().
  • sessionmock – The request.session to use. Defaults to mock.MagicMock().
  • messagesmock – The request._messages to use. Defaults to mock.MagicMock().
  • requestattributes (dict) – Extra attributes to the reques to object. This is applied before add_essential_cradmin_attributes_to_request(), so any of the attributes that method sets can not be in this dics.
  • viewkwargs (dict) – Kwargs for the view.
  • expected_statuscode (int) – Expected status code. If this is None, we do not validate the status code. Defaults to None.
  • htmls_selector (boolean) – If this is True, we create a htmls.S() object for the response content. Should normally not be used without also providing expected_statuscode because it can lead to unexpected behavior. Defaults to False.
  • verbose (boolean) – More verbose exception messages. Useful for debugging, but should be False when you are not debugging. Defaults to False.
class TestCaseMixin

Bases: django_cradmin.cradmin_testhelpers.AbstractTestCaseMixin

A mixin class that makes it easier to write tests for cradmin views.

It mocks all the required attributes of the request object.

Examples

Minimalistic:

from django_cradmin import cradmin_testhelpers

class TestMyView(TestCase, cradmin_testhelpers.TestCaseMixin):
    viewclass = MyView

    def test_get_render_form(self):
        mockresponse = self.mock_http200_getrequest_htmls()
        mockresponse.selector.prettyprint()

    def test_post(self):
        mockresponse = self.mock_postrequest(requestkwargs={
            'data': {
                'name': 'Jane Doe',
                'age': 24
            }
        })
        self.assertEqual(mockresponse.response.status_code, 302)

Adding optional HTTP headers if needed:

from django_cradmin import cradmin_testhelpers

class TestMyView(TestCase, cradmin_testhelpers.TestCaseMixin):
    viewclass = MyView

    def test_post_with_optional_httpheaders(self):
        self.mock_postrequest(
            cradmin_instance=cradmin_instance,
            httpheaders={
                'HTTP_REFERER': 'http://www.http-referent.com'
            },
            requestkwargs={
                'data': {
                    'name': 'Jane Doe',
                    'age': 24
                }
            })
        self.assertEqual(mockresponse.response.status_code, 302)

Customizing the request.body, if e.g you have created a view that works as an API that handles POST with data. This data will in most cases be JSON. If this is not done through a form, but javascript, the data will end up in request.body, and not request.POST. To have this functionality when testing, simply add the data you want to _body in requestattributes. request._body is the actual attribute, and request.body is a property:

from django_cradmin import cradmin_testhelpers

class TestMyView(TestCase, cradmin_testhelpers.TestCaseMixin):
    viewclass = MyView

    def test_post_with_optional_httpheaders(self):
        self.mock_postrequest(
            cradmin_instance=cradmin_instance,
            requestattributes={
                '_body': b'{'key': 'value'}'
            })
        self.assertEqual(mockresponse.response.status_code, 302)

Views that take arguments:

from django_cradmin import cradmin_testhelpers

class TestMyView(TestCase, cradmin_testhelpers.TestCaseMixin):
    viewclass = MyView

    def test_get_render_form(self):
        # The kwargs for mock_postrequest, mock_http200_getrequest_htmls
        # and mock_getrequest are the same, so only showing one for brevity.
        mockresponse = self.mock_http200_getrequest_htmls(viewkwargs={'pk': 10})

Views that use a querystring (GET):

from django_cradmin import cradmin_testhelpers

class TestMyView(TestCase, cradmin_testhelpers.TestCaseMixin):
    viewclass = MyView

    def test_get_render_form(self):
        mockresponse = self.mock_http200_getrequest_htmls(
            requestkwargs={
                'data': {
                    'orderby': 'name'
                }
            }
        )

Using a real user object:

from django_cradmin import cradmin_testhelpers

class TestMyView(TestCase, cradmin_testhelpers.TestCaseMixin):
    viewclass = MyView

    def test_post(self):
        requestuser = mommy.make(settings.AUTH_USER_MODEL)
        mockresponse = self.mock_http200_getrequest_htmls(requestuser=requestuser)

Mocking Django messages framework messages:

from django_cradmin import cradmin_testhelpers

class TestMyView(TestCase, cradmin_testhelpers.TestCaseMixin):
    viewclass = MyView

    def test_post(self):
        messagesmock = mock.MagicMock()
        mockresponse = self.mock_postrequest(
            requestkwargs={
                'data': {
                    'name': 'Jane Doe',
                    'age': 24
            },
            messagesmock=messagesmock
        )
        messagesmock.add.assert_called_once_with(
            messages.SUCCESS,
            'The data was posted successfully!',
            '')

Get a bit of extra information useful while debugging failing tests - use verbose=True (only for debugging, do not keep/commit verbose=True):

from django_cradmin import cradmin_testhelpers

class TestMyView(TestCase, cradmin_testhelpers.TestCaseMixin):
    viewclass = MyView

    def test_get(self):
        mockresponse = self.mock_http200_getrequest_htmls(
            verbose=True
        )
get_requestfactory_class()

Get the request factory class. Defaults to django.test.RequestFactory.

prettyformat_response_content(response)

Must be implemented in subclasses.

class NoLoginTestCaseMixin

Bases: django_cradmin.cradmin_testhelpers.TestCaseMixin

Use this instead of TestCaseMixin if you do not require an authenticated user in your view.

create_default_user_for_mock_request()

Overridden to return a django.contrib.auth.models.AnonymousUser object instead of creating a user.

class RestFrameworkApiTestCaseMixin

Bases: django_cradmin.cradmin_testhelpers.TestCaseMixin

Django-rest-framework API test case mixin.

Works just like TestCaseMixin, except that it has a different debug output, and no *_htmls methods.

Assumes that the viewclass is a subclass of rest_framework.views.APIView.

You can also make it work with viewsets by overriding make_view() and use return ViewSetClass.as_view({...}) there.

get_requestfactory_class()

Get the request factory class. Defaults to django.test.RequestFactory.

prettyformat_response_content(response)

Must be implemented in subclasses.

mock_request(**kwargs)

Create a mocked request using make_requestfactory() and mock.MagicMock.

Parameters:
  • method – The http method (get, post, …).
  • httpheaders (httpheaders) – Forwarded to make_minimal_request(). Extra HTTP headers to be added to request.META.
  • requestkwargs (dict) – Forwarded to make_minimal_request().
  • cradmin_role – The request.cradmin_role to use. Defaults to mock.MagicMock().
  • cradmin_app – The request.cradmin_app to use. Defaults to mock.MagicMock().
  • cradmin_instance – The request.cradmin_instance to use. Defaults to mock.MagicMock().
  • requestuser – The request.requestuser to use. Defaults to mock.MagicMock().
  • sessionmock – The request.session to use. Defaults to mock.MagicMock().
  • messagesmock – The request._messages to use. Defaults to mock.MagicMock().
  • requestattributes (dict) – Extra attributes to the reques to object. This is applied before add_essential_cradmin_attributes_to_request(), so any of the attributes that method sets can not be in this dics.
  • viewkwargs (dict) – Kwargs for the view.
  • expected_statuscode (int) – Expected status code. If this is None, we do not validate the status code. Defaults to None.
  • htmls_selector (boolean) – If this is True, we create a htmls.S() object for the response content. Should normally not be used without also providing expected_statuscode because it can lead to unexpected behavior. Defaults to False.
  • verbose (boolean) – More verbose exception messages. Useful for debugging, but should be False when you are not debugging. Defaults to False.

Utilities

Css classes only for automatic tests

You should use the cradmin_test_css_class() template tag to add css classes that are only used in tests.

If you extend django_cradmin.renderable.AbstractRenderableWithCss, you can add css classes only for tests by overriding get_test_css_class_suffixes_list().