初心者でも安心: Django テンプレート検証の基本から応用まで - assertHTMLNotEqual() を使いこなす


django.test.SimpleTestCase.assertHTMLNotEqual() は、Django テストフレームワークで HTML テンプレートのレンダリング結果を検証するためのアサーションです。2つの HTML 文字列を比較し、内容が異なることを確認します。これは、テンプレートが正しいコンテキストデータに基づいて異なるコンテンツを生成することを確認するのに役立ちます。

使い方

from django.test import SimpleTestCase

class MyTests(SimpleTestCase):
    def test_my_view(self):
        response = self.client.get('/my-view/')
        self.assertHTMLNotEqual(response.content, '<p>Hello, world!</p>')

この例では、/my-view/ URL に対する GET リクエストを行い、レスポンスの HTML コンテンツ (response.content) を取得します。そして、assertHTMLNotEqual() アサーションを使用して、そのコンテンツが '<p>Hello, world!</p>'異なる ことであることを確認します。

引数

assertHTMLNotEqual() は以下の引数を取ります。

  • actual_html
    実際の HTML 文字列
  • expected_html
    期待される HTML 文字列

比較方法

assertHTMLNotEqual() は、以下の方法で2つの HTML 文字列を比較します。

  1. 空白の除去
    両方の文字列から空白文字や改行文字を除去します。
  2. コメントの除去
    両方の文字列から HTML コメントを除去します。
  3. タグの属性の並べ替え
    両方の文字列の HTML タグの属性をアルファベット順に並べ替えます。
  4. 文字列の比較
    上記の処理で得られた2つの文字列を比較します。

注意点

  • テンプレート内で生成される HTML は、ランダムな要素 (例えば、セッション ID) を含む場合があります。このような要素を比較から除外したい場合は、strip_spaces_in_tags オプションを使用できます。
  • assertHTMLNotEqual() は、HTML の構造のみを比較します。スタイルやスクリプトなどの要素は考慮されません。

Django テストフレームワークには、HTML テンプレートのレンダリング結果を検証するための他にも様々なアサーションが用意されています。

  • assertNotContains(): HTML 文字列が特定の文字列 を含まない ことを確認します。
  • assertContains(): HTML 文字列が特定の文字列 を含む ことを確認します。
  • assertHTMLEqual(): 2つの HTML 文字列が 等しいことを確認します。


from django.test import SimpleTestCase

class MyTests(SimpleTestCase):
    def test_my_view(self):
        # コンテキストデータ 1
        context1 = {'name': 'Alice'}
        response1 = self.client.get('/my-view/', context=context1)
        html1 = response1.content

        # コンテキストデータ 2
        context2 = {'name': 'Bob'}
        response2 = self.client.get('/my-view/', context=context2)
        html2 = response2.content

        # テンプレートが異なるコンテキストデータに基づいて異なるコンテンツを生成することを確認
        self.assertHTMLNotEqual(html1, html2)

例 2: テンプレートが特定の文字列を含むことを確認する

from django.test import SimpleTestCase

class MyTests(SimpleTestCase):
    def test_my_view(self):
        response = self.client.get('/my-view/')
        self.assertContains(response.content, '<p>Hello, world!</p>')

例 3: テンプレートが特定の文字列を含まないことを確認する

from django.test import SimpleTestCase

class MyTests(SimpleTestCase):
    def test_my_view(self):
        response = self.client.get('/my-view/')
        self.assertNotContains(response.content, '<p>Goodbye, world!</p>')
from django.test import SimpleTestCase

class MyTests(SimpleTestCase):
    def test_my_view(self):
        response = self.client.get('/my-view/')
        self.assertHTMLNotEqual(response.content, '<p>Hello, world!</p>', strip_spaces_in_tags=True)


代替方法の選択肢

  • assertNotEqual() と strip_tags() の組み合わせ
    • assertNotEqual() アサーションを使用して、レンダリングされた HTML テンプレートの テキストコンテンツ を比較します。
    • strip_tags() 関数を使用して、HTML タグをすべて削除してから比較を行います。
from django.test import SimpleTestCase
from django.utils.html import strip_tags

class MyTests(SimpleTestCase):
    def test_my_view(self):
        response = self.client.get('/my-view/')
        expected_text = '<p>Hello, world!</p>'
        actual_text = strip_tags(response.content)
        self.assertNotEqual(actual_text, expected_text)
  • BeautifulSoup を使用
    • BeautifulSoup ライブラリを使用して、レンダリングされた HTML テンプレートを解析します。
    • 解析結果を比較して、テンプレートが期待通りにレンダリングされていることを確認します。
from django.test import SimpleTestCase
from bs4 import BeautifulSoup

class MyTests(SimpleTestCase):
    def test_my_view(self):
        response = self.client.get('/my-view/')
        soup = BeautifulSoup(response.content, 'html.parser')
        expected_html = '<p>Hello, world!</p>'
        actual_html = str(soup.find('p'))
        self.assertNotEqual(actual_html, expected_html)

それぞれの方法の利点と欠点

方法利点欠点
assertNotEqual() + strip_tags()シンプルで分かりやすいHTML 構造の情報が失われる
BeautifulSoup詳細な比較が可能より複雑なコードが必要
  • テンプレートの構造も比較したい場合は、BeautifulSoup を使用する方法が適しています。
  • テンプレートのテキストコンテンツのみを比較したい場合は、assertNotEqual() + strip_tags() が最もシンプルで効果的な方法です。
  • サードパーティ製ライブラリを使用する
  • カスタムアサーションを作成する