Django テストを実装する

シェアする

Django でテストを実装します。

私は今までテストを実装したいと思っても、テストを実装していませんでしたが、プロジェクトが大きくなるとデグレード(デグレ)が酷く、何とかこの状況を改善したいと思い、テストを実装し始めました。実際にテストを実装すると、意外に簡単に実装できることがわかります。

テストを実装することで、リグレッションテストができ、デグレ防止だけでなく、コードレビューでレビューする側が、テストコード部分の動作を確認する必要がなくなり、レビュー時間の短縮にも貢献します。

CI ツールと組み合わせることで、自動でテストすることもできますし、テストを実装することで、様々な恩恵を受けることができます。

完成イメージ

$ python3.6 manage.py test app
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
....
----------------------------------------------------------------------
Ran 4 tests in 0.018s

OK
Destroying test database for alias 'default'...
$

バージョン

  • Python 3.6.4
  • Django 2.0.3

インストール

Python, Django

Python と Django のインストールは、Python Web フレームワーク Django の環境を構築するの記事を参考にしてください。

実装

views.py

from django.shortcuts import render

def index(request):
    return render(request, 'app/index.html')

def plus(a, b):
    return a + b

def is_true():
    return True

def is_none():
    return None

テスト対象となる views.py です。4つの関数を実装しました。

tests.py

from django.urls import reverse
from django.test import TestCase, Client

class ViewsTest(TestCase):
    def test_index(self):
        response = Client().get(reverse('index'))
        self.assertEqual(response.status_code, 200)

class FuncTest(TestCase):
    def test_plus(self):
        from app.views import plus
        self.assertEqual(plus(1, 1), 2)

    def test_true(self):
        from app.views import is_true
        self.assertTrue(is_true())

    def test_none(self):
        from app.views import is_none
        self.assertIsNone(is_none())

views.py のテストを実装します。

テストは、Django の TestCase を使います。Django の TestCase は、Python unittest の TestCase を継承していますので、テストの合否を判断する関数は、unittest の TestCase 関数を使用します。

テストの合否を判断する関数は、たくさんありますので、詳細はリファレンスを確認してください。ここでは、その中の一部を取り上げます。

assertEqual

引数を2つ渡し、等価であれば、テストが合格します。この関数が一番使用頻度が高いと思います。

assertTrue

引数を1つ渡し、True であれば、テストが合格します。

assertIsNone

引数を1つ渡し、None であれば、テストが合格します。

補足

tests.py としていますが、tests ディレクトリを作って、test_views.py や test_forms.py とした方が見通しが良くなります。

テスト

test コマンド

$ python3.6 manage.py test app
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
....
----------------------------------------------------------------------
Ran 4 tests in 0.018s

OK
Destroying test database for alias 'default'...
$

テストの実行は、manage.py の test コマンドを使います。

実行すると、上記のような出力なります。

今回実装したテストの関数は4つで、テストは関数毎に実行しますので、 Ran 4 tests となっています。1つの関数に複数のテストを入れてしまうと、テストが失敗したときに、どこで失敗したのかがわからなくなります。特別な理由がない限り、1つの関数にテストは1つまでとした方が良いと思います。

まとめ

Django のテストを実装しました。

Django のテスト(というか、Python の unittest)には、実行前に呼び出される setUp() 、実行後に呼び出させる tearDown() など便利な機能がたくさんありますし、フィクスチャーやモックなどを使わないといけないケースも出てくると思います。

テストの実装について、覚えることはまだたくさんあると思いますが、デグレのないシステムを実現するために、これからもテストを実装し続けていきたいと思います。