General Usage
*************
Reminder that the **Django-Expanded-Test-Cases** package is meant to expand the
existing Django
`TestCase `_
class and
`UnitTesting `_
logic with some extra functionality.
Below are examples using this in practice:
Functionality Example #1 - Minimal Test
=======================================
In any given web framework, the most common use case is to generate some page
response from a url. So if you wanted a basic test to check that a given
`url reverse `_
renders the expected page, you might need to:
* Log in with a specific testing user, if the url is behind a login wall.
* Generate the reverse of a provided url string.
* Fetch the response that generates at that url.
* Decode and parse the ``response.content`` for some uniquely identifiable
attribute, such as the
tag.
* Verify the located
tag contents match the expected value.
In standard Python code, this may look roughly like:
.. code:: python
"""Standard test, using Django's base testing functionality."""
import re
from django.contrib.auth import get_user_model
from django.test import TestCase
from django.urls import reverse
class TestProjectViews(TestCase):
def test_response_header():
user = get_user_model().objects.get(username='john1234')
self.client.force_login(user)
url = reverse('my-url-reverse-string', args=(url_args,))
response = self.client.get(url, follow=True)
content = response.content.decode('utf-8')
response_header = re.search(r'
([\S\s]+)
', response)
self.assertEqual('Expected H1 Value', response_header)
Alternatively, using the **Django-Expanded-Test-Cases** package, we can use the
``assertPageHeader()`` function to simplify that same check down to:
.. code:: python
"""Slightly simplified test, using provided assertPageHeader() function."""
from django.urls import reverse
from django_expanded_test_cases import IntegrationTestCase
class TestProjectViews(IntegrationTestCase):
def test_response_header():
self.client.force_login(self.get_user('john1234'))
url = reverse('my-url-reverse-string', args=(url_args,))
response = self.client.get(url, follow=True)
self.assertPageHeader(response, 'Expected H1 Value')
As you can see, we were able to eliminate quite a bit of setup. But, we can
then use the ``assertResponse()`` check to simplify this even further:
.. code:: python
"""Extremely simplified test, using provided assertResponse() function."""
from django_expanded_test_cases import IntegrationTestCase
class TestProjectViews(IntegrationTestCase):
def test_response_header():
self.test_user = self.get_user('john1234')
self.assertResponse('my-url-reverse-string', url_args, expected_header='Expected H1 Value')
.. note::
The three above code snippets are effectively equivalent in what they
accomplish.
As you can see, the **Django-Expanded-Test-Cases** package isn't doing anything
groundbreaking, per say. Yet it makes the same test significantly easier and
faster to write, allowing the developer to focus on the actual meat and bones
of the test, rather than wasting significant time writing repeated code to
simply generate response objects and pull values from them.
Writing tests in such a way will also generally reduce the amount of visual
clutter in a test, resulting in project tests that are generally more
immediately obvious as to exactly what is being tested.
Functionality Example #2 - Ordered Content Check
================================================
This is a more complicated example than above. Here, we:
* Log in with a specific testing user.
* Generate the reverse of a given url string.
* Fetch a response at the url.
* Check the response for a set of page content, expected to be in a specific
order.
For formatting and readability purposes, this is a single assertion that's
broken into multiple lines.
.. code:: python
"""Ordered page content test, using provided assertGetResponse() function."""
from django_expanded_test_cases import IntegrationTestCase
class TestProjectViews(IntegrationTestCase):
def test_page_contents():
self.assertGetResponse(
'my_project:todo-list',
expected_content=[
'TODO List',
'
',
'
Wake up
',
'
Have breakfast
',
'
Go to work
',
'
Fix my Django tests
',
'
Have dinner
',
'
',
],
user='john1234',
)
Functionality Example #3 - Form Submission Check
================================================
We can also test POST responses, to check that a page handles data submission as
expected. In this example, we:
* Log in with a specific testing user.
* Generate the reverse of a given url string.
* Fetch a response at the url, after providing mock form data as part of a POST
request.
* Check the rendered page response for:
* A page title, to ensure we're at the page we expect.
* A page header, to further ensure we're at the page we expect.
* Context page messages that we expect to return on form submission success.
* A few content strings we expect to see on the page.
For formatting and readability purposes, this is a single assertion that's
broken into multiple lines.
.. code:: python
"""Form submission test, using provided assertPostResponse() function."""
from django_expanded_test_cases import IntegrationTestCase
class TestProjectViews(IntegrationTestCase):
def test_form_submission():
self.assertPostResponse(
'my_project:survey',
data={'favorite_color': 1, 'additional_comments': 'I like stuff'}
expected_title='Home | My Site',
expected_header='Welcome to my Project Home',
expected_messages=[
'Form submitted!',
'We thank you for taking our survey.',
],
expected_content=[
'Welcome to our site!',
'Please try our products',
],
user='john1234',
)
Functionality Example #4 - Repeating HTML Element Check
=======================================================
In cases where we expect an html element to repeat a number of times, we can
call the ``assertRepeatingElement()`` function. In this example, we:
* Call the ``assertGetResponse()`` function to initially generate a response.
* Within this assertion, we only check the page title and header, to verify
we're loading the page we expect.
* We save the return value (aka the page content) to a variable.
* Call the ``assertRepeatingElement()`` function, to actually do the work we
want.
In this case, we check for a total of 10
elements, within a specific
subsection of page content.
For formatting and readability purposes, this is two separate assertions, with
each one broken into multiple lines.
.. code:: python
"""
Using the assertRepeatingElement() function to check that multiple instances
of a given element exist.
"""
from django_expanded_test_cases import IntegrationTestCase
class TestProjectViews(IntegrationTestCase):
def test_response_header():
page_content = self.assertGetResponse(
'my_project:lists-page',
expected_title='My Lists | My Site',
expected_header='Header for Lists Page',
user='john1234',
)
assertRepeatingElement(
page_content,
'