[Fixed]-How to test (using unittest) the HTML output of a Django view?

12👍

These other answers are now out of date regarding assertions. The assertion assertHTMLEqual (since Django 1.4) takes care of things like ignoring whitespace, and ignoring the order of attributes.

For example (from the docs):

from django.test import TestCase

class MyTest(TestCase):

    def test_some_html(self):
        # A passing test that doesn't raise an AssertionError.
        self.assertHTMLEqual(
            '<input type="checkbox" checked="checked" id="id_accept_terms" />',
            '<input id="id_accept_terms" type="checkbox" checked>'
        )

In practice, one of the arguments to assertHTMLEqual would be dynamically generated.

14👍

I’ve always found a combination of BeautifulSoup, and assertContains and assertFormError from TestCase’s available assertions to do the trick.

9👍

Django’s test framework is ideal for this.

  1. Check the status code and content.
    http://docs.djangoproject.com/en/1.2/topics/testing/#django.test.TestCase.assertContains

  2. Check the template. http://docs.djangoproject.com/en/1.2/topics/testing/#django.test.TestCase.assertTemplateUsed

Also, it helps to use id="something" tags within your HTML to make it easier to find things when unit testing. We have tests like this.

def should_find_something( self ):
    response= self.client.get( "/path/to/resource/pk/" )
    self.assertContains( response, '<td id="pk">the pk string</td>', status_code=200 )
    self.assertTemplateUsed( response, 'appropriate_page.html' )

Works nicely.

👤S.Lott

2👍

Here is the solution with BeautifulSoup:

import bs4 as bs


class HtmlTestMixin:
    maxDiff = None

    def assertElementContains(self, request_content, html_element="", html_selectors={}, element_text=""):
        soup = bs.BeautifulSoup(request_content,  "html.parser")
        element = soup.find(html_element, **html_selectors)
        soup_1 = bs.BeautifulSoup(element_text, "html.parser")
        self.assertEqual(str(element.prettify()), soup_1.prettify())

It can be called like:

        self.assertElementContains(
            response.content,
            "select",
            {"id": "order-model"},
            '''
            <select name="order" id="order-model" class="form-select">
                <option value="_score" >
                   Score
                </option>
            </select>
             ''',
        )

1👍

Have a look at Django with asserts – which uses lxml.

https://django-with-asserts.readthedocs.org/en/latest/

Leave a comment