Python
Django

DjangoでWebサービスを作る - 2.アプリを作ってみる その6

前回の記事「アプリを作ってみる その5」では投票用のフォームを追加し、viewをGeneric Viewで置き換えることでコーディングを最低限に抑えた。これでひとまずアプリと呼べる形になった。今回はチュートリアル05に沿ってテストの作成に関してみていく。

記事一覧と開発環境

こちら

アプリを作ってみる その6

初回の手順で仮想環境を立ち上げておく

Djangoでテストをする基本的なアプローチは3つある

  1. Django用のテストツールでtests.pyに自動化スクリプトを作る
  2. shellを使ってinteractive実行する
  3. unittest等のdjango外部のテストツールを使う

通常は1のやり方。
テストケースを作る段階や、ひとまず確認したいようなときは2のやり方
djangoプロジェクトのみでなく、より大きいプログラム単位でまとめてテストを管理するような場合は3のアプローチがよさそう。あとはseleniumとかを使ってユーザ操作のテストをするようなときも3でもよいかもしれない。

3に関しては、要は2のやり方をunittestのスクリプトに書くような感じなので、1と2の概要をまとめる。

tests.pyでテストする

python manage.py startapp pollsしたときにデフォルトでtests.pyが作られる。これにテストケースを追加していく。

mysite/polls/tests.py
import datetime
from django.test import TestCase
from django.utils import timezone
from django.urls import reverse
from .models import Question

class QuestionModelTest(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)

今回はデフォルトのtests.pyを使うが、スクリプト名はtestで始まれば何でもよい。
テストケースはTestCaseを拡張したクラス内のmethodとして定義する。クラスないのtestで始まるmethodがすべて実行される。

使い勝手はunittest等とほぼ同じ。

shellを使ってinteractive実行する

python manage.py shellする

: from django.test.utils import setup_test_environment
: setup_test_environment()
: from django.test import Client
: client = Client()
: from django.urls import reverse
: response = client.get(reverse('polls:index'))
: response.status_code
200
: response.content
b'\n    <ul>\n    \n        <li><a href="/polls/3/">What time is it now?</a></li>\n    \n        <li><a href="/polls/2/">How are you?</a></li>\n    \n        <li><a href="/polls/1/">What&#39;s up</a></li>\n    \n    </ul>\n\n'
>>

setup_test_environment()はtemplate renderer等をインストールする。interactive実行するときには必要。tests.pyの時は不要。
Clientクラスもinteractiveの時や、外部テストシステムを使うときのみ必要。tests.pyで使うときはTestCaseクラスが持っているself.clientを代わりに使える。
例えば上記のコマンドはtests.pyでやるなら以下のような感じ。

mysite/polls/tests.py
class ClientGetRequestTest(TestCase):

   def test_do_the_same_as_shell_test(self):

       response = self.client.get(reverse('polls:index'))
       self.assertEquals(response.status_code, 200 )        

テストに関する詳細はこちら。次回はjavascriptや画像ファイル、CSS等の外部ファイルと連携する方法を確認する。

参考文献

[1] Django - tutorial: Writing your first Django app, part 5
[2] Testing tools