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