Djangoプロジェクトにユニットテストを追加する方法

提供:Dev Guides
移動先:案内検索

著者は、 Open Internet / Free Speech Fund を選択して、 Write forDOnationsプログラムの一環として寄付を受け取りました。

序章

エラーなしで最初から完全に機能するWebサイトを構築することはほぼ不可能です。 そのため、Webアプリケーションをテストしてこれらのエラーを見つけ、プロアクティブに対処する必要があります。 テストの効率を向上させるために、テストをWebアプリケーションの特定の機能をテストするユニットに分割するのが一般的です。 この方法は、ユニットテストと呼ばれます。 テストはプロジェクトの小さな部分(ユニット)に他の部分から独立して焦点を当てているため、エラーの検出が容易になります。

Webサイトのテストは、HTTP要求の処理、フォームの検証、テンプレートのレンダリングなどのロジックの複数のレイヤーで構成されているため、実行するのが複雑なタスクになる可能性があります。 ただし、 Django は、Webアプリケーションのテストをシームレスにする一連のツールを提供します。 Djangoでは、テストを作成するための推奨される方法は、Python unittest モジュールを使用することですが、他のテストフレームワークを使用することもできます。

このチュートリアルでは、Djangoプロジェクトにテストスイートをセットアップし、アプリケーションのモデルとビューの単体テストを記述します。 これらのテストを実行し、その結果を分析して、テストの失敗の原因を見つける方法を学びます。

前提条件

このチュートリアルを開始する前に、次のものが必要です。

ステップ1—Djangoアプリケーションにテストスイートを追加する

Djangoのテストスイートは、プロジェクト内のすべてのアプリのすべてのテストケースのコレクションです。 Djangoテストユーティリティがお持ちのテストケースを検出できるようにするには、名前がtestで始まるスクリプトでテストケースを記述します。 このステップでは、テストスイートのディレクトリ構造とファイルを作成し、その中に空のテストケースを作成します。

Django Development チュートリアルシリーズに従うと、blogsiteというDjangoアプリが作成されます。

すべてのテストスクリプトを保持するフォルダを作成しましょう。 まず、仮想環境をアクティブ化します。

cd ~/my_blog_app
. env/bin/activate

次に、blogsiteアプリディレクトリ(models.pyおよびviews.pyファイルを含むフォルダー)に移動し、testsという名前の新しいフォルダーを作成します。

cd ~/my_blog_app/blog/blogsite
mkdir tests

次に、このフォルダーをPythonパッケージに変換するので、__init__.pyファイルを追加します。

cd ~/my_blog_app/blog/blogsite/tests
touch __init__.py

次に、モデルをテストするためのファイルと、ビューをテストするためのファイルを追加します。

touch test_models.py
touch test_views.py

最後に、test_models.pyに空のテストケースを作成します。 Django TestCaseクラスをインポートして、独自のテストケースクラスのスーパークラスにする必要があります。 後で、このテストケースにメソッドを追加して、モデルのロジックをテストします。 ファイルtest_models.pyを開きます。

nano test_models.py

次に、次のコードをファイルに追加します。

〜/ my_blog_app / blog / blogsite / tests / test_models.py

from django.test import TestCase

class ModelsTestCase(TestCase):
    pass

これで、blogsiteアプリにテストスイートが正常に追加されました。 次に、ここで作成した空のモデルテストケースの詳細を入力します。

ステップ2—Pythonコードをテストする

このステップでは、models.pyファイルに記述されたコードのロジックをテストします。 特に、Postモデルのsaveメソッドをテストして、呼び出されたときに投稿のタイトルの正しいスラッグが作成されることを確認します。

Postモデルのsaveメソッドのmodels.pyファイルに既にあるコードを確認することから始めましょう。

cd ~/my_blog_app/blog/blogsite
nano models.py

次のように表示されます。

〜/ my_blog_app / blog / blogsite / models.py

class Post(models.Model):
    ...
    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = slugify(self.title)
        super(Post, self).save(*args, **kwargs)
    ...

保存しようとしている投稿にスラッグ値があるかどうかをチェックし、ない場合はslugifyを呼び出してスラッグ値を作成していることがわかります。 これは、投稿を保存するときにスラッグが実際に作成されることを確認するためにテストする可能性のあるロジックのタイプです。

ファイルを閉じます。

これをテストするには、test_models.pyに戻ります。

nano test_models.py

次に、それを次のように更新し、強調表示された部分を追加します。

〜/ my_blog_app / blog / blogsite / tests / test_models.py

from django.test import TestCase
from django.template.defaultfilters import slugify
from blogsite.models import Post


class ModelsTestCase(TestCase):
    def test_post_has_slug(self):
        """Posts are given slugs correctly when saving"""
        post = Post.objects.create(title="My first post")

        post.author = "John Doe"
        post.save()
        self.assertEqual(post.slug, slugify(post.title))

この新しいメソッドtest_post_has_slugは、"My first post"というタイトルの新しい投稿を作成し、その投稿に作成者を与えて保存します。 この後、Python unittestモジュールのassertEqualメソッドを使用して、投稿のスラッグが正しいかどうかを確認します。 assertEqualメソッドは、渡された2つの引数が"=="演算子によって決定されたものと等しいかどうかをチェックし、等しくない場合はエラーを発生させます。

test_models.pyを保存して終了します。

これは、テストできるものの例です。 プロジェクトに追加するロジックが多いほど、テストする必要があります。 saveメソッドにロジックを追加したり、Postモデルの新しいメソッドを作成したりする場合は、ここにさらにテストを追加する必要があります。 それらをtest_post_has_slugメソッドに追加したり、新しいテストメソッドを作成したりできますが、名前はtestで始まる必要があります。

Postモデルのテストケースが正常に作成され、保存後にスラッグが正しく作成されたと主張しました。 次のステップでは、ビューをテストするためのテストケースを作成します。

ステップ3—Djangoのテストクライアントを使用する

このステップでは、Djangoテストクライアントを使用してビューをテストするテストケースを作成します。 テストクライアントは、ダミーのWebブラウザーとして機能するPythonクラスであり、ユーザーと同じようにビューをテストしてDjangoアプリケーションを操作できます。 テストメソッドでself.clientを参照すると、テストクライアントにアクセスできます。 たとえば、test_views.pyでテストケースを作成しましょう。 まず、test_views.pyファイルを開きます。

nano test_views.py

次に、以下を追加します。

〜/ my_blog_app / blog / blogsite / tests / test_views.py

from django.test import TestCase


class ViewsTestCase(TestCase):
    def test_index_loads_properly(self):
        """The index page loads properly"""
        response = self.client.get('your_server_ip:8000')
        self.assertEqual(response.status_code, 200)

ViewsTestCaseには、Djangoテストクライアントを使用してWebサイトのインデックスページ(http://your_server_ip:8000your_server_ipはのIPアドレス)にアクセスするtest_index_loads_properlyメソッドが含まれています。使用しているサーバー)。 次に、テストメソッドは応答のステータスコードが200であるかどうかを確認します。これは、ページがエラーなしで応答したことを意味します。 その結果、ユーザーがアクセスしたときにもエラーなしで応答することを確認できます。

ステータスコードとは別に、 Django Documentation TestingResponsesページでテストできるテストクライアントレスポンスの他のプロパティについて読むことができます。

このステップでは、インデックスページをレンダリングするビューがエラーなしで機能することをテストするためのテストケースを作成しました。 これで、テストスイートに2つのテストケースがあります。 次のステップでは、それらを実行して結果を確認します。

ステップ4—テストの実行

プロジェクトの一連のテストの作成が完了したので、次はこれらのテストを実行して結果を確認します。 テストを実行するには、blogフォルダー(アプリケーションのmanage.pyファイルを含む)に移動します。

cd ~/my_blog_app/blog

次に、それらを次のように実行します。

python manage.py test

端末に次のような出力が表示されます。

OutputCreating test database for alias 'default'...
System check identified no issues (0 silenced).
..
----------------------------------------------------------------------
Ran 2 tests in 0.007s

OK
Destroying test database for alias 'default'...

この出力には、2つのドット..があり、それぞれが合格したテストケースを表しています。 次に、test_views.pyを変更して、失敗したテストをトリガーします。 まず、次のファイルを開きます。

nano test_views.py

次に、強調表示されたコードを次のように変更します。

〜/ my_blog_app / blog / blogsite / tests / test_views.py

from django.test import TestCase


class ViewsTestCase(TestCase):
    def test_index_loads_properly(self):
        """The index page loads properly"""
        response = self.client.get('your_server_ip:8000')
        self.assertEqual(response.status_code, 404)

ここでは、ステータスコードを200から404に変更しました。 次に、manage.pyを使用してディレクトリからテストを再実行します。

python manage.py test

次の出力が表示されます。

OutputCreating test database for alias 'default'...
System check identified no issues (0 silenced).
.F
======================================================================
FAIL: test_index_loads_properly (blogsite.tests.test_views.ViewsTestCase)
The index page loads properly
----------------------------------------------------------------------
Traceback (most recent call last):
  File "~/my_blog_app/blog/blogsite/tests/test_views.py", line 8, in test_index_loads_properly
    self.assertEqual(response.status_code, 404)
AssertionError: 200 != 404

----------------------------------------------------------------------
Ran 2 tests in 0.007s

FAILED (failures=1)
Destroying test database for alias 'default'...

失敗したスクリプト、テストケース、およびメソッドを示す説明的な失敗メッセージがあることがわかります。 また、失敗の原因も示されます。この場合、ステータスコードは404と等しくなく、メッセージAssertionError: 200 != 404が表示されます。 ここでのAssertionErrorは、test_views.pyファイルの強調表示されたコード行で発生します。

〜/ my_blog_app / blog / blogsite / tests / test_views.py

from django.test import TestCase


class ViewsTestCase(TestCase):
    def test_index_loads_properly(self):
        """The index page loads properly"""
        response = self.client.get('your_server_ip:8000')
        self.assertEqual(response.status_code, 404)

これは、アサーションがfalseであること、つまり、応答ステータスコード(200)が予期されたもの(404)ではないことを示しています。 失敗メッセージの前に、2つのドット...Fに変更されていることがわかります。これは、最初のテストケースが合格し、2番目のテストケースが合格しなかったことを示しています。

結論

このチュートリアルでは、Djangoプロジェクトでテストスイートを作成し、テストモデルとビューロジックにテストケースを追加し、テストの実行方法を学び、テスト出力を分析しました。 次のステップとして、models.pyおよびviews.pyにないPythonコード用の新しいテストスクリプトを作成できます。

以下は、Djangoを使用してWebサイトを構築およびテストするときに役立つ可能性のあるいくつかの記事です。

その他のチュートリアルやプロジェクトについては、Djangoトピックページを確認することもできます。