
【第7回】Djangoで日記アプリを作ろう ~Djangoでテスト実施編~
2021.12.20
【第7回】Djangoで日記アプリを作ろう ~Djangoでテスト実施編~
前回は、Django テンプレート言語について学びました。
今回は、Django のテストについて学んでいきましょう!
この記事では主に、以下の内容を学んでいきます。
- テスト実行の流れ
- テストの実装方法
- テストの出力の意味
テストの実装方法よりも、Django におけるテストの実行の流れに焦点を当てます。
そのフローが理解できれば、あとはテストケースを考え、コードに落とし込むだけです。
Django におけるテストの実装は、Python が標準で提供する、unittest に沿っています。
なので、そこまで目新しいものはありません。
前回の記事
Djnagoにおけるテスト処理の流れ
それではまず、Django における、テストフローの大枠を掴みましょう!
細かいところは、後ほど補足をしていきます。
Django では、テスト用のコマンドを実行すると、下記の流れでテストを実行します。
- test.py ファイルより、テストコードを探索
- テストで利用するデータベースを作成し、マイグレーションを実施
- テストコードを実行
- 全テストを実施した後、テスト用データベースを削除(削除せずに残すことも可能)
test.py ファイルよりテストコードを探索
まず、test.py というテスト専用のファイルの中から、実行するテストを探索します。
test.py は、アプリケーションディレクトリの中に配置されています。
diar ディレクトリの中を、確認してみましょう!
test.py が配置されていることが、確認できるはずです。
1 2 3 4 5 6 7 8 9 10 11 12 | diary/ ├── __init__.py ├── admin.py ├── apps.py ├── forms.py ├── migrations │ ├── 0001_initial.py │ └── __init__.py ├── models.py ├── tests.py # テストケースを実装するファイル ├── urls.py └── views.py |
テスト用のデータベースの作成とマイグレーション
テスト実施に必要な、テスト用データベースを作成しましょう!
次に、models.py の中身を元に、マイグレーションを実施します。
基本的にデータベースは、settings.py の DATABASES の設定を参照して、自動的に作成されます。
つまり、特に何も設定しなくても、テストは実行できるわけですね!
設定が必要となってくるのは、テスト実行後にデータベースを残しておき、その中身を確認したい場合です。
この場合には、テスト用の名前を指定すると、後ほどデータベースへの接続がしやすくなります。
例えば、テスト用データベースの名前を「mytestdb」とする場合、DATABASES 辞書に TEST キーを割り当て、NAME を設定します。
1 2 3 4 5 6 7 8 | DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': BASE_DIR / 'db.sqlite3', 'TEST': { 'NAME': 'mytestdb', }} } |
データベースを残す必要性がないのであれば、TEST キーを付与しなくても構いません。
TEST キーを付与しない場合には、Django のデフォルト設定に従います。
このとき、default に設定した NAME に「test_」という接頭語を付けた値が、テスト用データベースの名前になります。
テストコードを実行
テストコードの探索とデータベースの作成が済んだので、いよいよテストを実行します。
なおテストは、django.test モジュールの TestCase を継承したクラスの中で、メソッドとして実装されます。
当然、1つのテスト用クラスの中に、複数のテスト用メソッドを定義することが可能です。
例えば、日記モデル用のテストクラスを作成し、その中に、
- 日記データの保存と取得をテストするメソッド
- 件数の一致を確かめるメソッド
などを、それぞれ実装していきます。
テスト用のデータベースの削除
全てのテストコードの実行が完了すると、テスト用データベースは削除されます。
データベースを新規作成し、最後に削除を実施するには、データベースの接続ユーザーに「create」と「delete」の権限が付与されている必要があります。
SQLite3 ではなく、PostgreSQL などの他のデータベースを利用している場合、ユーザーに対して付与されている権限に注意しましょう。
テストを実装してみよう
それでは、実際にテストを実装して実行してみましょう。
diary アプリケーションの中の test.py に、日記モデルに関するテストを実施する、DiaryModelTest クラスを作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | import datetime from django.test import TestCase from .models import Diary class DiaryModelTests(TestCase): def test_diary_has_date(self): """ 作成した日記データに日付が付与されているか確認 """ Diary.objects.create(title='test_title', text='test_text') actual_diary = Diary.objects.get(title='test_title') self.assertIsInstance(actual_diary.date, datetime.date) def test_save_and_retrieve(self): """ 日記データの保存と取得を確認 """ Diary.objects.create(title='test_title', text='test_text') actual_diary = Diary.objects.get(title='test_title') self.assertEqual(actual_diary.title, 'test_title') |
このコードのポイントは2つ。
ポイント1
1つ目は、DiaryModelTest が TestCase クラスを継承していることです。
このクラスを継承していないと、テスト用のコードとして見なされません。
ポイント2
2つ目は、「test_」から始まるメソッドを定義していることです。
テスト用メソッドは、必ず「test_」という接頭語を付与します。
では、このテストを実行してみます。
以下のコマンドを実行しましょう!
python3 manage.py test
以下のような出力が確認できれば、作成した2件のテストが、無事実行できています。
1 2 3 4 5 6 7 8 | Creating test database for alias 'default'... Destroying old test database for alias 'default'... .. ---------------------------------------------------------------------- Ran 2 tests in 0.030s OK Destroying test database for alias 'default'... |
出力を理解しよう
最後に、テストの出力について、理解を深めましょう。
先ほどの出力は、「2件のテストが成功した」程度の情報しかありませんでした。
ですが、出力のレベルを調整すれば、より深い情報を得られます。
以下のコマンドを実行してみましょう。
python3 manage.py test -v 2
すると、以下のような出力が得られるはずです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | Creating test database for alias 'default' ('mytestdb')... Destroying old test database for alias 'default' ('mytestdb')... Operations to perform: Synchronize unmigrated apps: bootstrap4, messages, staticfiles, widget_tweaks Apply all migrations: admin, auth, contenttypes, diary, sessions Synchronizing apps without migrations: Creating tables... Running deferred SQL... Running migrations: Applying contenttypes.0001_initial... OK Applying auth.0001_initial... OK Applying admin.0001_initial... OK Applying admin.0002_logentry_remove_auto_add... OK Applying admin.0003_logentry_add_action_flag_choices... OK Applying contenttypes.0002_remove_content_type_name... OK Applying auth.0002_alter_permission_name_max_length... OK Applying auth.0003_alter_user_email_max_length... OK Applying auth.0004_alter_user_username_opts... OK Applying auth.0005_alter_user_last_login_null... OK Applying auth.0006_require_contenttypes_0002... OK Applying auth.0007_alter_validators_add_error_messages... OK Applying auth.0008_alter_user_username_max_length... OK Applying auth.0009_alter_user_last_name_max_length... OK Applying auth.0010_alter_group_name_max_length... OK Applying auth.0011_update_proxy_permissions... OK Applying auth.0012_alter_user_first_name_max_length... OK Applying diary.0001_initial... OK Applying diary.0002_auto_20201121_1025... OK Applying diary.0003_remove_diary_deleted_at... OK Applying diary.0004_auto_20201220_1225... OK Applying diary.0005_auto_20201220_1227... OK Applying sessions.0001_initial... OK System check identified no issues (0 silenced). test_diary_has_date (diary.tests.DiaryModelTests) 作成した日記データに日付が付与されているか確認 ... ok test_save_and_retrieve (diary.tests.DiaryModelTests) 日記データの保存と取得を確認 ... ok ---------------------------------------------------------------------- Ran 2 tests in 0.058s OK Destroying test database for alias 'default' ('mytestdb')... |
まず、mytestdb というデータベースを作成し、マイグレーションが実行されています。
その後、DiaryModelTests クラスに定義された、各種テストメソッドが順番に実行されていますね。
最後に、mytestdb が削除(destroy)され、全ての処理が完了です。
これは、前の章で学んだ、テストの実施フロー通りです。
第8回へつづく!
今回は、Django におけるテストについて学びました!
次回は、django-allauth というライブラリを用いて、認証機能を実装していきます。
次回もお楽しみに!
第8回はこちら!
こちらの記事もオススメ!
書いた人はこんな人

- 「好きを仕事にするエンジニア集団」の(株)ライトコードです!
ライトコードは、福岡、東京、大阪の3拠点で事業展開するIT企業です。
現在は、国内を代表する大手IT企業を取引先にもち、ITシステムの受託事業が中心。
いずれも直取引で、月間PV数1億を超えるWebサービスのシステム開発・運営、インフラの構築・運用に携わっています。
システム開発依頼・お見積もり大歓迎!
また、現在「WEBエンジニア」「モバイルエンジニア」「営業」「WEBデザイナー」「WEBディレクター」を積極採用中です!
インターンや新卒採用も行っております。
以下よりご応募をお待ちしております!
https://rightcode.co.jp/recruit
ITエンタメ10月 13, 2023Netflixの成功はレコメンドエンジン?
ライトコードの日常8月 30, 2023退職者の最終出社日に密着してみた!
ITエンタメ8月 3, 2023世界初の量産型ポータブルコンピュータを開発したのに倒産!?アダム・オズボーン
ITエンタメ7月 14, 2023【クリス・ワンストラス】GitHubが出来るまでとソフトウェアの未来