
目次
はじめに
Django を学習するには、何はともあれ公式チュートリアル「はじめての Django アプリ作成」からスタートしてみるのが良いでしょう。しかし、いざチュートリアル通りに進めようとしても躓く場合も多いと思います。そこで、「チュートリアルの進め方」シリーズとして、チュートリアルに沿った作業を行いながら補足事項をまとめることにしました。チュートリアルで躓いた際のヒントとしてお使いください。
利用環境は Ubuntu、 Linux Mint を中心として説明しますが、 Windows についても補足します。
前回は、Django チュートリアルの進め方 その 4 (2) と題してはじめての Django アプリ作成、その 4の後半についてまとめました。
今回は、はじめての Django アプリ作成、その 5 の前半についてまとめました。
初めてのテスト作成
バグを見つけたとき
公開日が未来の日付であった場合に、was_published_recently() がどのような動作をするか shell で確認します。
$ python manage.py shell >>> import datetime >>> from django.utils import timezone >>> from polls.models import Question >>> future_question = Question(pub_date=timezone.now() + datetime.timedelta(days=30)) >>> future_question.was_published_recently() True
5行目で、30日後の公開日の Question を作成しています。
was_published_recently() は「最近公開された質問か?」を判断するメソッドですが、30日後に公開される (まだ公開されていない) 予定の質問に対して True を返してしまっています。つまりバグです。
バグをあぶり出すためにテストを作成する
shell でテストした内容をテストコードにします。
polls/tests.py に下記を記述します。
import datetime from django.test import TestCase from django.utils import timezone from .models import Question class QuestionModelTests(TestCase): def test_was_published_recently_with_future_question(self): """ was_published_recently() returns False for questions whose pub_date is in the future. """ time = timezone.now() + datetime.timedelta(days=30) future_question = Question(pub_date=time) self.assertIs(future_question.was_published_recently(), False)
TestCase を継承したクラスに、test で始まるメソッドを追加。メソッド中で評価用のメソッド (ここでは assertIs()) を実行。という手順です。
django.test.TestCase は Python の標準のユニットテストクラスである TestCase を拡張したものです。基本的な使い方は unittest.TestCase のリファレンスを参照してください。下記は、主な検査用メソッドの抜粋です。
メソッド | 確認事項 |
assertEqual(a, b) | a == b |
assertNotEqual(a, b) | a != b |
assertTrue(x) | bool(x) is True |
assertFalse(x) | bool(x) is False |
assertIs(a, b) | a is b |
assertIsNot(a, b) | a is not b |
assertIsNone(x) | x is None |
assertIsNotNone(x) | x is not None |
assertIn(a, b) | a in b |
assertNotIn(a, b) | a not in b |
assertIsInstance(a, b) | isinstance(a, b) |
assertNotIsInstance(a, b) | not isinstance(a, b) |
テストの実行
テストを実行します。(manage.py test アプリケーション名)
$ python manage.py test polls Creating test database for alias 'default'... System check identified no issues (0 silenced). F ====================================================================== FAIL: test_was_published_recently_with_future_question (polls.tests.QuestionModelTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/jade/workspace/mysite/polls/tests.py", line 18, in test_was_published_recently_with_future_question self.assertIs(future_question.was_published_recently(), False) AssertionError: True is not False ---------------------------------------------------------------------- Ran 1 test in 0.002s FAILED (failures=1) Destroying test database for alias 'default'...
バグを修正する
was_published_recently() が未来日付で True を返さないように修正します。
def was_published_recently(self): now = timezone.now() return now - datetime.timedelta(days=1) <= self.pub_date <= now
再度テストを実行します。
$ python manage.py test polls Creating test database for alias 'default'... System check identified no issues (0 silenced). . ---------------------------------------------------------------------- Ran 1 test in 0.000s OK Destroying test database for alias 'default'...
より包括的なテスト
テストを完成させます。
import datetime from django.test import TestCase from django.utils import timezone from .models import Question class QuestionModelTests(TestCase): def test_was_published_recently_with_future_question(self): """ was_published_recently() returns False for questions whose pub_date is in the future. """ time = timezone.now() + datetime.timedelta(days=30) future_question = Question(pub_date=time) self.assertIs(future_question.was_published_recently(), False) def test_was_published_recently_with_old_question(self): """ was_published_recently() returns False for questions whose pub_date is older than 1 day. """ time = timezone.now() - datetime.timedelta(days=1, seconds=1) old_question = Question(pub_date=time) self.assertIs(old_question.was_published_recently(), False) def test_was_published_recently_with_recent_question(self): """ was_published_recently() returns True for questions whose pub_date is within the last day. """ time = timezone.now() - datetime.timedelta(hours=23, minutes=59, seconds=59) recent_question = Question(pub_date=time) self.assertIs(recent_question.was_published_recently(), True)
公開日が前日より前、前日以降、未来の3パターンでテストするようにしています。
再度テストを実行してみます。
$ python manage.py test polls Creating test database for alias 'default'... System check identified no issues (0 silenced). ... ---------------------------------------------------------------------- Ran 3 tests in 0.001s OK Destroying test database for alias 'default'...
3つのテストすべて合格した事がわかります。
今回はテストの基本についてまとめました。次回は はじめての Django アプリ作成、その 5 の後半、ビューのテストについてまとめます。
参考
-
- Django チュートリアルの進め方 その 1
- Django チュートリアルの進め方 その 2 (1)
- Django チュートリアルの進め方 その 2 (2)
- Django チュートリアルの進め方 その 2 (3)
- Django チュートリアルの進め方 その 3 (1)
- Django チュートリアルの進め方 その 3 (2)
- Django チュートリアルの進め方 その 4 (1)
- Django チュートリアルの進め方 その 4 (2)
- Django チュートリアルの進め方 その 5 (1)
- Django チュートリアルの進め方 その 5 (2)
- Django チュートリアルの進め方 その 6
- Django チュートリアルの進め方 その 7