【簡単】djangoで簡単なテストケースを作成する

# 目的
django-restframeworkで簡単なAPIを作成しているが、そのAPIで簡単なテストをすることで、早めにバグや問題を見つけて修正したいと思った。
そのため簡単なテストケースを作成しようと思う。

# 実施環境
### ハードウェア環境
| 項目 | 情報 |
|:-:|:-:|
| OS  |macOS Catalina(10.15.7)   |
|ハードウェア   |  MacBook Air (11-inch, Early 2015) |
|プロセッサ   | 1.6 GHz デュアルコアIntel Core i5|
|メモリ   |  4 GB 1600 MHz DDR3 |
|グラフィックス   |  intel HD Graphics 6000 1536 MB |
### ソフトウェア環境
| 項目 | 情報 |
|:-:|:-:|
| homebrew  | 3.3.8 |
| mysql | Ver 8.0.27 for macos10.15 on x86_64 |
| python  | 3.8.12 |
| anaconda  | 4.10.1 |
| django  | 3.0.0 |
| pip  | 3.1.2 |

# 前提
models.pyでテスト対象となるDBのモデルを作成済みであること。

# モデル紹介
今回テストするモデルは下記のようなJobsモデル。
このJobsモデルのテストを行おうと思う。
**具体的にはJobsモデルにレコードを問題なく登録し、取得できているかなどを確認する。**

```models.py
class Jobs(models.Model):
    job_name = models.CharField(max_length=20, verbose_name='職業名')
    average_salary = models.IntegerField(verbose_name='平均収入')
    paid_holiday_count = models.IntegerField(verbose_name='有給数')
    is_holiday_on_weekend = models.BooleanField(verbose_name='土日休みか')
    
    def __str__(self):
        return self.job_name
```


# testファイルの作成場所
testファイルの作成場所としてはアプリディレクトリのtests.pyでテストを行ってもいいのだが、わかりやすくテストを見るために複数ファイルに分けることとする。

そのためアプリディレクトリにtestsディレクトリを作成し、その中に```test_```から始まるテストファイルを作成する。

```
.
├── __init__.py
├── admin.py
├── apps.py
├── migrations
├── models.py
├── serializer.py
├── tests
│   ├── __init__.py
│   └── test_models.py
├── urls.py
└── views.py
```
# テストケース作成

```test_models.py
from django.test import TestCase
from ..models import *

class JobsModelTests(TestCase):
    def test_empty(self):
        """登録前にJobsテーブルが空だということを確認"""  
        # Jobsテーブルの全レコード取得
        saved_jobs = Jobs.objects.all()
        # まだ何も登録してないからsaved_jobsの数は0
        self.assertEqual(saved_jobs.count(), 0)

    def test_only_one_record_made(self):
        """レコード1つ作成した後にDB内にレコードが一つだけあることを確認"""
        # 1つレコードを適当に作成
        job = Jobs(
            job_name='singer',
            average_salary=10000,
            is_holiday_on_weekend=True,
            paid_holiday_count=100
        )
        # レコードをDBに保存
        job.save()
        # Jobテーブルの全レコード取得
        saved_job = Jobs.objects.all()
        # 全レコード合計: 1を確認
        self.assertEqual(saved_job.count(), 1)
    
    def test_before_after_save(self):
        """データを保存し、保存したばかりのJobテーブルのレコードと、保存前が同じ値であることを確認"""
        job = Jobs(
            job_name='writer',
            average_salary=10000,
            is_holiday_on_weekend=True,
            paid_holiday_count=100
        )
        job.save()
        # 保存したばかりのJobテーブルのレコード取得
        saved_job = Jobs.objects.first()
        # 保存したjobを取得したものと保存前のjobを比較
        self.assertEqual(saved_job, job)
```

```
self.assertEqual()
```
は引数1つ目と２つ目が同じ値かをテストし、同じでない場合はエラーを出す。


ざっくりとこのような形でJobsモデルのテストを行なっている。
1. 登録前にJobsテーブルが空だということを確認
2. レコード1つ作成した後にDB内にレコードが一つだけあることを確認
3. データを保存し、保存したばかりのJobテーブルのレコードと、保存前が同じ値であることを確認




## 実際に叩いてみる

一番簡単でシンプルなテストの実行コマンドは

```
$ python manage.py test
```
オプションで色々あるがここでは割愛する。

実際にこのコマンドを叩き、何もエラーがない場合:

```
Creating test database for alias 'default'...
[INFO]	asctime:2022-01-07 14:10:30,306	module:views	message:<QuerySet []>	process:3840	thread:4725464512
System check identified no issues (0 silenced).
...
----------------------------------------------------------------------
Ran 3 tests in 0.008s

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

#### エラーがある場合:

```test_models.py
class JobsModelTests(TestCase):
    def test_is_empty(self):
        """登録前にJobsテーブルが空だということを確認"""  
        # Jobsテーブルの全レコード取得
        saved_jobs = Jobs.objects.all()
        # まだ何も登録してないからsaved_jobsの数は0
        self.assertEqual(saved_jobs.count(), 1)
```
```self.assertEqual(saved_jobs.count(), 1)```
この部分でまだ何も登録していないのでDBから取得したレコードが１件あるということになっているため、下記のようにエラーとなる。

```
Creating test database for alias 'default'...
[INFO]	asctime:2022-01-07 14:36:31,011	module:views	message:<QuerySet []>	process:4176	thread:4673158592
System check identified no issues (0 silenced).
F..
======================================================================
FAIL: test_is_count_one (tinder.tests.test_models.JobsModelTests)
1つレコードを適当に作成すると、レコードが1つだけカウントされることをテスト
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/a0210198/Desktop/dev/api_practice/tinder_api/tinder/tests/test_models.py", line 25, in test_is_count_one
    self.assertEqual(saved_job.count(), 2)
AssertionError: 1 != 2

----------------------------------------------------------------------
Ran 3 tests in 0.010s

FAILED (failures=1)
Destroying test database for alias 'default'...
```
このようにtestが失敗した場合は関数名のしたのコメントとともにどこで失敗したかがわかる。


# 参考文献

https://zenn.dev/tmasuyama1114/articles/django-how-to-unit-test