fixtureを使ってdjangoでテストしてみる

fixtureを使ってdjangoでテストしてみる

前回のこちらの記事でdumpdataを取ったのでそれを使ってテストをしてみたいと思います。
下の参考の記事の方と同じところでハマってしまいました...

参考:
  ・unittest --- ユニットテストフレームワーク¶
  ・Pythonのunittestでハマったところと、もっと早くに知りたかったこと
  ・テスト用モジュールを分割する方法

階層

階層は下の通りです。


django_project
├── manage.py
└── myapp
    ├── fixtures
    │   └── data.json # 1.用意
    ├── tests
    │   ├── __init__.py # 2.作成
    │   └── test_writer_model.py # 4.作成
    └── tests_org.py # 3.編集

「# 1.用意」は、前回の記事で作成したdumpdataになります。
「# 2.作成」は、__init__.pyを配置してパッケージ化しています。(参考参照)
「# 3.編集」は、testsディレクトリとtests.pyでバッティングしてしまうので名前を適当に変更しています。テストコードが少量に収まるのであればtests.pyに記載してもよいそうですが肥大化するのを避けるためにtestsディレクトリの配下にテストコード用のファイル(# 4)を分けて作成するようです。(参考参照)
「# 4.作成」は、テストコードです。ファイル名はtest__xxx.pyと言う規則があるようです。(参考参照)

モデル

models.pyは下の通りです。


from django.db import models


class Writer(models.Model):
    name = models.CharField(max_length=128)


class Article(models.Model):
    writer = models.ForeignKey(Writer,
                               on_delete=models.CASCADE,
                               related_name='articles')
    title = models.CharField(max_length=512)
    contents = models.TextField()

データ

data.jsonの中身は下の通りです。


+----+-----------+
| id | name      |
+----+-----------+
|  1 | satoh     |
|  2 | suzuki    |
|  3 | takahashi |
|  4 | furukawa  |
+----+-----------+

テストコード

今回のテストコードは簡単にmyapp_writerテーブルに4名のオブジェクトが登録されているかどうかを確認するテストコードを書いてみます。一つ気を付けないといけないのは、ファイル名同様にメソッド名は必ずdef test_xxxとする規則がある事です。「fixtures = ['data.json']」は作成したdumpdataを読み込みテスト用データベースを作成します。(実行コマンドにオプションを付けないとテスト後に自動で破棄されます)


from django.test import TestCase
from myapp.models import Writer


class TestWriterModel(TestCase):
    fixtures = ['data.json']

    def test_count_writers(self):
        writers = Writer.objects.all()
        self.assertEqual(writers.count(), 4)

実行

実行は下記の通り種類があります。


# djangoproject内全てのテストコードを実行する。~特定のメソッドのテストコード一つのみ実行する。
python manage.py test
python manage.py test myapp
python manage.py test myapp.tests
python manage.py test myapp.tests.test_writer_model
python manage.py test myapp.tests.test_writer_model.TestWriterModel
python manage.py test myapp.tests.test_writer_model.TestWriterModel.test_count_writers

実行結果

実行結果は下記の通り成功しているのでOKと出力されます。


Creating test database for alias 'default'...
System check identified no issues (0 silenced).
.
----------------------------------------------------------------------
Ran 1 test in 0.032s

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

「 self.assertEqual(writers.count(), 4)」を「 self.assertEqual(writers.count(), 5)」にして実行してみます。


Creating test database for alias 'default'...
System check identified no issues (0 silenced).
F
======================================================================
FAIL: test_count_writers (myapp.tests.test_writer_model.TestWriterModel)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/web/django_project/myapp/tests/test_writer_model.py", line 10, in test_count_writers
    self.assertEqual(writers.count(), 5)
AssertionError: 4 != 5

----------------------------------------------------------------------
Ran 1 test in 0.027s

FAILED (failures=1)
Destroying test database for alias 'default'...

「AssertionError: 4 != 5」って出力されてますね。

printしてみる

カウントしたのが本当に著者なのか確認したい時はprintをしてもよいかもしれません。


from django.test import TestCase
from myapp.models import Writer


class TestWriterModel(TestCase):
    fixtures = ['data.json']

    def test_count_writers(self):
        writers = Writer.objects.all()
        for writer in writers:
            print(writer.name)
        self.assertEqual(writers.count(), 5)

# 実行結果
# Creating test database for alias 'default'...
# System check identified no issues (0 silenced).
# satoh
# suzuki
# takahashi
# furukawa
# F
# ======================================================================
# FAIL: test_count_writers (myapp.tests.test_writer_model.TestWriterModel)
# ----------------------------------------------------------------------
# Traceback (most recent call last):
#   File "/home/web/django_project/myapp/tests/test_writer_model.py", line 12, in test_count_writers
#     self.assertEqual(writers.count(), 5)
# AssertionError: 4 != 5
#
# ----------------------------------------------------------------------
# Ran 1 test in 0.034s
#
# FAILED (failures=1)
# Destroying test database for alias 'default'...

きちんと著者名が表示されているのが確認できました。

YouTube