niwoshi
Posted on January 20, 2022
Django REST framework(以下DRF)のテストについて軽くまとめておきます。
一応前回の続きという事で進めて行きます。
正直Djangoのテストは慣れていないのでなにからやれば良いか試行錯誤している段階ではあります。
テストフォルダの作成
DRFの場合、テスト対象としてはアプリケーション毎にモデル、シリアライザ、ビューの3種類が考えられます。
startapp
で自動生成されるapiv1/tests.py
にテストを書いていってもいい気もしますが、上記3種のテストを1ファイルに書いてしまうと肥大化していくのは目に見えているので、上記を分離しておきます。
apiv1/tests
フォルダを作成して
apiv1/tests/__init__.py
apiv1/tests/test_models.py
apiv1/tests/test_serializers.py
apiv1/tests/test_views.py
の用にテストファイルを作成します。(必要なものだけで大丈夫かと思います。)
__init__.py
は空ファイルで大丈夫です。ついでに
apiv1/tests.py
は削除しておきます。
ビューのテスト
今回はDRFのviewsetsをそのまま継承して利用しているだけなので、おそらくテストは不要だと思います。
とはいえ一応チュートリアル的な観点で試したいのでTodoの生成だけテストを書いておきます。apiv1/tests/test_views.py
を作成します。
from django.urls import reverse
from rest_framework.test import APITestCase
from todos.models import Todo
class TodoCreateTests(APITestCase):
def test_create_success(self):
params = {
"title": "test_create_success",
}
url = reverse("apiv1:todos-list")
response = self.client.post(url, params, format="json")
self.assertEqual(Todo.objects.count(), 1)
self.assertEqual(response.status_code, 201)
todo = Todo.objects.get()
expected_json_dict = {
"id": str(todo.id),
"title": todo.title,
"checked": todo.checked,
}
self.assertJSONEqual(response.content, expected_json_dict)
def test_create_bad_request(self):
params = {
"title": "",
}
url = reverse("apiv1:todos-list")
response = self.client.post(url, params, format="json")
self.assertEqual(Todo.objects.count(), 0)
self.assertEqual(response.status_code, 400)
下記コマンドで全テストが捜索され実行されます。
python manage.py test
アプリケーションやクラスを指定して実行もできますが、ここでは割愛します。
シリアライザのテスト
シリアライザのテストは、実際のリクエストを受け入れる際のバリデーションと、レスポンスを返す時の出力内容を検証すれば大丈夫だと思います。引き続き、apiv1/tests/test_serializers.py
を作成します。
from django.test import TestCase
from todos.models import Todo
from ..serializers import TodoSerializer
class TodoSerializerTest(TestCase):
def test_input_valid(self):
input_data = {"title": "test_input_valid"}
serializer = TodoSerializer(data=input_data)
self.assertEqual(serializer.is_valid(), True)
def test_input_invalid_if_title_is_blank(self):
input_data = {"title": ""}
serializer = TodoSerializer(data=input_data)
self.assertEqual(serializer.is_valid(), False)
self.assertCountEqual(serializer.errors.keys(), ["title"])
self.assertCountEqual([x.code for x in serializer.errors["title"]], ["blank"])
def test_output_data(self):
todo = Todo.objects.create(
title="test_output_data",
)
serializer = TodoSerializer(instance=todo)
expected_data = {
"id": str(todo.id),
"title": todo.title,
"checked": todo.checked,
}
self.assertDictEqual(serializer.data, expected_data)
とはいえ、先ほどのビューのテストで作成を検証していて、title
がブランクの時にエラーがでる処理を検証しているので少し被っている気もします。
上記の例で言えばシリアライザのテストのみでいいと思いますが、そもそもviewsetsを利用している場合は開発段階で十分テストされていると思うので、省略してしまっても大丈夫だと思います。
モデルのテスト
こちらは通常のDjangoでのテストと変わらないので割愛します。
参考
Posted on January 20, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.