Djangoプロジェクトにユニットテストを追加する方法
著者は、 Open Internet / Free Speech Fund を選択して、 Write forDOnationsプログラムの一環として寄付を受け取りました。
序章
エラーなしで最初から完全に機能するWebサイトを構築することはほぼ不可能です。 そのため、Webアプリケーションをテストしてこれらのエラーを見つけ、プロアクティブに対処する必要があります。 テストの効率を向上させるために、テストをWebアプリケーションの特定の機能をテストするユニットに分割するのが一般的です。 この方法は、ユニットテストと呼ばれます。 テストはプロジェクトの小さな部分(ユニット)に他の部分から独立して焦点を当てているため、エラーの検出が容易になります。
Webサイトのテストは、HTTP要求の処理、フォームの検証、テンプレートのレンダリングなどのロジックの複数のレイヤーで構成されているため、実行するのが複雑なタスクになる可能性があります。 ただし、 Django は、Webアプリケーションのテストをシームレスにする一連のツールを提供します。 Djangoでは、テストを作成するための推奨される方法は、Python unittest モジュールを使用することですが、他のテストフレームワークを使用することもできます。
このチュートリアルでは、Djangoプロジェクトにテストスイートをセットアップし、アプリケーションのモデルとビューの単体テストを記述します。 これらのテストを実行し、その結果を分析して、テストの失敗の原因を見つける方法を学びます。
前提条件
このチュートリアルを開始する前に、次のものが必要です。
- プログラミング環境がセットアップされたサーバーにDjangoがインストールされています。 これを行うには、DjangoWebフレームワークのインストール方法とプログラミング環境のセットアップチュートリアルのいずれかに従うことができます。
- モデルとビューで作成されたDjangoプロジェクト。 このチュートリアルでは、 DjangoDevelopmentチュートリアルシリーズのプロジェクトに従いました。
ステップ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:8000
、your_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ユニットテストドキュメント
- ScalingDjangoチュートリアルシリーズ
その他のチュートリアルやプロジェクトについては、Djangoトピックページを確認することもできます。