Djangoチュートリアル⑥（自動テスト）

# はじめに

[Djangoチュートリアル⑤（汎用ビュー）](https://qiita.com/honda28/items/7150a5df0213dc6a3927)に続いて、[はじめての Django アプリ作成、その 5](https://docs.djangoproject.com/ja/3.1/intro/tutorial05/#writing-your-first-django-app-part-5)に沿ってチュートリアルを進めていく。チュートリアルだけでは理解できないので、[現場で使える Django の教科書（基礎編）](https://www.amazon.co.jp/%E7%8F%BE%E5%A0%B4%E3%81%A7%E4%BD%BF%E3%81%88%E3%82%8B-Django-%E3%81%AE%E6%95%99%E7%A7%91%E6%9B%B8%E3%80%8A%E5%9F%BA%E7%A4%8E%E7%B7%A8%E3%80%8B-%E6%A8%AA%E7%80%AC-%E6%98%8E%E4%BB%81/dp/4802094744)も読みながら進める。

# 自動テストの導入

ここまでアプリケーションの動作に関することのみ実行してきたが、ここでテストを作成する。自動テストを作ることで、プログラムが正しく動作していることの確認が一瞬ででき、エラーが発生していた場合にはどこでそれが起きたのかをすばやく見極めることができる。テストを作成する時間はかかるが、テストなしで実装した場合のデバッグと比べても大きく時間を節約することができるため非常に意味がある。その他にも、ソフト自体の信頼度が上がったり複数人で開発をした場合にも他者のコードを自分が破壊したり、また自分のコードを他者が破壊することを防ぐことができる。

Django では アプリケーションのテストを tests.py というファイルに記述することで、テスト実行時に自動的にテストを見つけて実行してくれる。たとえば、polls アプリケーションのテストは polls/tests.py にテストを書く。具体的には、__django.test.TestCase クラスを継承したクラスの、名前が test で始まるメソッドをテストとして実行__する。チュートリアルでは、TestCase を継承した QuestionModelTests というサブクラスを作成し、未来の日付の pub_date を持つ Question のインスタンスを生成して、それに対する was_published_recently() の出力をチェックする test_was_published_recently_with_future_question() というメソッドを記述している。

```python: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)
```

コード中の assertIs(a, b) というメソッドは、「a is b」となるかどうかのテストを実行しており、was_published_recently() の出力が False となっていれば、テストは成功となる。Python では unittest という標準ライブラリがあり、ここで使用している TestCase というクラスはこれを拡張しているらしい。assertIs 以外にも便利な assert メソッドはあるのでそれらは [assert メソッド一覧](https://docs.python.org/ja/3/library/unittest.html#assert-methods)を参照。

# テストの実行

以下コマンドで、作成したテストを polls アプリケーションのテストを実行できる。

```
$ python manage.py test polls
```

テストの結果以降、コードの編集等は[はじめての Django アプリ作成、その 5](https://docs.djangoproject.com/ja/3.1/intro/tutorial05/#writing-your-first-django-app-part-5)を参照することとし、説明はここまでとする。

# テストにおいて多いことはいいことだ

このようにテストを作成していくと、似たようなテストがたくさんできたり、重複があったりとなっていくことが想定される。しかし、__テストにおいては多いことはいいこと__であり、たとえ冗長であっても一度テストを作成すればあとはそれを実行するだけで多くの恩恵を得られる。テストを整理さえすれば、テストがいくら膨大になろうと問題はないため、以下のようなルールを意識してテストを作成することが推奨されている。

- モデルやビューごとに TestClass を分割する
- テストしたい条件の集まりのそれぞれに対して、異なるテストメソッドを作る
- テストメソッドの名前は、その機能を説明するようなものにする

# さらなるテスト

チュートリアルでは、モデルの内部ロジックやビューに関するテストを作成したが、それらはほんの一部で他にも多くの便利なツールが用意されている。たとえば、Web アプリケーションの UI テストや JavaScript のテストを行える Selenium のようなフレームワークを使うことができる LiveServerTestCase がある。他にもコミット時に自動的にテストを実行することや、コードカバレッジをチェックしてテストされていないコードを発見することも重要とのこと。そのあたりは今後進めていった際に、利用して再度記事にしたい。

# おわりに

初心者のため、unittest ライブラリを含めこんなに便利なツールがあることを知らなかった。テストを意識したアプリ開発をできるように慣れていこう。引き続き、[はじめての Django アプリ作成、その 6](https://docs.djangoproject.com/ja/3.1/intro/tutorial06/)を進めていく。

関連記事のリンクは以下。
- [Djangoチュートリアル①（インストールとプロジェクトの作成）](https://qiita.com/honda28/items/34dceaeeb1cdddb4c9dd)
- [Djangoチュートリアル②（ビューの作成）](https://qiita.com/honda28/items/c91f78238ea3d53e776d)
- [Djangoチュートリアル③（モデルの作成、Django Admin）](https://qiita.com/honda28/items/04bc74c28b816aa10e2c)
- [Djangoチュートリアル④（テンプレート）](https://qiita.com/honda28/items/f62dc31e470ef3901706)
- [Djangoチュートリアル⑤（汎用ビュー）](https://qiita.com/honda28/items/7150a5df0213dc6a3927)
- [Djangoチュートリアル⑦（静的ファイル）](https://qiita.com/honda28/items/bd0bfe8731a17609907c)