LoginSignup
0
0

[Django]Serializerのテストを作成してみる

Last updated at Posted at 2024-05-06

はじめに

自分用の個人開発のメモ/備忘録として記録していきます。

環境

django5.0
↓ dockerでの開発環境作成はこちら

↓ 認証ユーザーモデルはこちらをそのまま利用

やりたいこと

Serializerのテストを一通り書いてみる

前回

Modelのテスト

Viewのテスト

テストについて下調べ

おもに下記のようなテストをやる模様。

No カテゴリ 内容
1 シリアライザインスタンスの作成 テスト対象のシリアライザインスタンスを作成
2 バリデーションテスト シリアライザが適切なバリデーションルールを適用していることを確認
3 シリアライズプロセスのテスト オブジェクトが正しいJSONデータにシリアライズされるかをテスト
4 デシリアライズプロセスのテスト JSONデータが正しくモデルインスタンスにデシリアライズされるかをテスト
5 フィールドレベルのテスト 定義したフィールドが適切に処理されているかを確認

準備

とりあえずSerializerを準備

・ユーザー>プロジェクト>リスト>チケット>コメントとリレーションしているモデルを利用
・チケットはコメントをネストしたTicketDetailSerializerを別途準備
・プロジェクトは、リスト>チケットまでをネストしたProjectDetailSerializerを準備

serializers.py
from rest_framework  import serializers
from .models import Project, List, Ticket, Comment

class CommentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Comment
        fields = '__all__'

class TicketSerializer(serializers.ModelSerializer):
    class Meta:
        model = Ticket
        fields = '__all__'

class ListSerializer(serializers.ModelSerializer):
    class Meta:
        model = List
        fields = '__all__'

class ProjectSerializer(serializers.ModelSerializer):
    user = serializers.HiddenField(default=serializers.CurrentUserDefault())
    class Meta:
        model = Project
        fields = '__all__'

class TicketDetailSerializer(serializers.ModelSerializer):
    comments = CommentSerializer(many=True)
    class Meta:
        model = Ticket
        fields = '__all__'

class ListDetailSerializer(serializers.ModelSerializer):
    tickets = TicketSerializer(many=True)
    class Meta:
        model = List
        fields = '__all__'

class ProjectDetailSerializer(serializers.ModelSerializer):
    user = serializers.HiddenField(default=serializers.CurrentUserDefault())
    lists = ListDetailSerializer(many=True)
    class Meta:
        model = Project
        fields = '__all__'

test_serializers.pyを書いていく

setUp

テストのセットアップ
メソッドを使用してテストケースの初期データを設定
各テスト実行前に自動的に呼び出され、テストに必要なデータを生成
ProjectSerializerがCurrentUserDefault()を使っているので、APIRequestFactoryにてリクエストを作成し、userを割り当て
シリアライザに context パラメータを渡すことで、シリアライザ内で request を使用出来るようにする

test_serializers.py
class ProjectSerializerTestCase(TestCase):
    def setUp(self):
        User = get_user_model()
        self.user = User.objects.create_user(email='testuser@test.com', password='12345')
        self.project_data = data={'name': 'Example Project', 'description': 'Example Description'}
        self.factory = APIRequestFactory()
        self.request = self.factory.get('/')  # メソッドは何でもよい、リクエストを作る必要がある
        self.request.user = self.user  # テストユーザーをリクエストに割り当てる

test_serializer_with_empty_data

空のデータに対するバリデーション
このテストメソッドは、空のデータでシリアライザを初期化し、そのバリデーションが失敗することを検証

test_serializers.py
def test_serializer_with_empty_data(self):
    serializer = ProjectSerializer(data={}, context={'request': self.request})
    self.assertFalse(serializer.is_valid())
    self.assertIn('name', serializer.errors)        
    self.assertNotIn('user', serializer.errors)

test_serializer_with_valid_data

有効なデータに対するバリデーション
シリアライザに渡されたデータが有効であり、is_valid() メソッドが True を返すことを検証

test_serializers.py
def test_serializer_with_valid_data(self):
    serializer = ProjectSerializer(data=self.project_data, context={'request': self.request})
    self.assertTrue(serializer.is_valid())

test_serializer_outputs_expected_data

シリアライズプロセスの検証
モデルインスタンスが正確にJSON形式にシリアライズされることを確認

test_serializers.py
def test_serializer_outputs_expected_data(self):
    model_instance = Project.objects.create(name='Example Project', user=self.user)
    serializer = ProjectSerializer(model_instance, context={'request': self.request})
    self.assertEqual(serializer.data['name'], 'Example Project')
    self.assertNotIn('user', serializer.data)

test_deserialization_creates_proper_instance

デシリアライズとインスタンスの作成
提供されたデータからモデルインスタンスが正しく作成されることを確認

test_serializers.py
    def test_deserialization_creates_proper_instance(self):
        serializer = ProjectSerializer(data=self.project_data,  context={'request': self.request})
        self.assertTrue(serializer.is_valid())
        instance = serializer.save()
        self.assertEqual(instance.name, 'Example Project')
        self.assertEqual(instance.user, self.user)

*CommentSerializer/TicketSerializer/ListSerializerも同様に作成する

TicketDetailSerializer(JSON形式へのシリアライズのみ)

test_serializers.py
class TicketDetailSerializerTestCase(TestCase):
    def setUp(self):
        User = get_user_model()
        self.user = User.objects.create_user(email='testuser@test.com', password='12345')
        self.project = Project.objects.create(name='Example Project', user=self.user)
        self.list = List.objects.create(title='Example List', project=self.project)
        self.ticket = Ticket.objects.create(title='Example Ticket', list=self.list)
        self.comment = Comment.objects.create(text='Example Comment', ticket=self.ticket)
    
    def test_serializer_outputs_expected_data(self):
        serializer = TicketDetailSerializer(self.ticket)
        self.assertEqual(serializer.data['title'], 'Example Ticket')
        self.assertEqual(serializer.data['list'], self.list.id)
        self.assertEqual(serializer.data['comments'][0]['text'], 'Example Comment')
        self.assertEqual(serializer.data['comments'][0]['ticket'], self.ticket.id)

ListDetailSerializer(JSON形式へのシリアライズのみ)

test_serializers.py
class ListDetailSerializerTestCase(TestCase):
    def setUp(self):
        User = get_user_model()
        self.user = User.objects.create_user(email='testuser@test.com', password='12345')
        self.project = Project.objects.create(name='Example Project', user=self.user)
        self.list = List.objects.create(title='Example List', project=self.project)
        self.ticket = Ticket.objects.create(title='Example Ticket', list=self.list)
    
    def test_serializer_outputs_expected_data(self):
        serializer = ListDetailSerializer(self.list)
        self.assertEqual(serializer.data['title'], 'Example List')
        self.assertEqual(serializer.data['project'], self.project.id)
        self.assertEqual(serializer.data['tickets'][0]['title'], 'Example Ticket')
        self.assertEqual(serializer.data['tickets'][0]['list'], self.list.id)

ProjectDetailSerializer(JSON形式へのシリアライズのみ)

test_serializers.py
class ProjectDetailSerializerTestCase(TestCase):
    def setUp(self):
        User = get_user_model()
        self.user = User.objects.create_user(email='testuser@test.com', password='12345')
        self.project = Project.objects.create(name='Example Project', user=self.user)
        self.list = List.objects.create(title='Example List', project=self.project)
        self.ticket = Ticket.objects.create(title='Example Ticket', list=self.list)
    
    def test_serializer_outputs_expected_data(self):
        serializer = ProjectDetailSerializer(self.project)
        self.assertEqual(serializer.data['name'], 'Example Project')
        self.assertNotIn('user', serializer.data)
        self.assertEqual(serializer.data['lists'][0]['title'], 'Example List')
        self.assertEqual(serializer.data['lists'][0]['project'], self.project.id)
        self.assertEqual(serializer.data['lists'][0]['tickets'][0]['title'], 'Example Ticket')
        self.assertEqual(serializer.data['lists'][0]['tickets'][0]['list'], self.list.id)

test実行

テスト実行

python manage.py test

全てのテストが成功すればこのような表示となる

Found 19 test(s).
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
...................
----------------------------------------------------------------------
Ran 19 tests in 4.555s

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

おわりに

・serializerが複雑になれば、もっとテストも細かく作成する必要がありそう

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0