From 6dc7af3e01eb1b9f74a8eb1ba8fd07b5e45a3644 Mon Sep 17 00:00:00 2001 From: Claude Paroz Date: Sat, 26 Sep 2015 11:02:09 +0200 Subject: [PATCH] Separated JSON serialization tests --- tests/serializers/test_json.py | 273 +++++++++++++++++++++++++++++ tests/serializers/tests.py | 261 +-------------------------- tests/serializers_regress/tests.py | 6 - 3 files changed, 274 insertions(+), 266 deletions(-) create mode 100644 tests/serializers/test_json.py diff --git a/tests/serializers/test_json.py b/tests/serializers/test_json.py new file mode 100644 index 0000000000..4239dcef8d --- /dev/null +++ b/tests/serializers/test_json.py @@ -0,0 +1,273 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +import json +import re + +from django.core import serializers +from django.core.serializers.base import DeserializationError +from django.test import TestCase, TransactionTestCase + +from .models import Score +from .tests import SerializersTestBase, SerializersTransactionTestBase + + +class JsonSerializerTestCase(SerializersTestBase, TestCase): + serializer_name = "json" + pkless_str = """[ + { + "pk": null, + "model": "serializers.category", + "fields": {"name": "Reference"} + }, { + "model": "serializers.category", + "fields": {"name": "Non-fiction"} + }]""" + mapping_ordering_str = """[ +{ + "model": "serializers.article", + "pk": %(article_pk)s, + "fields": { + "author": %(author_pk)s, + "headline": "Poker has no place on ESPN", + "pub_date": "2006-06-16T11:00:00", + "categories": [ + %(first_category_pk)s, + %(second_category_pk)s + ], + "meta_data": [] + } +} +] +""" + + @staticmethod + def _validate_output(serial_str): + try: + json.loads(serial_str) + except Exception: + return False + else: + return True + + @staticmethod + def _get_pk_values(serial_str): + ret_list = [] + serial_list = json.loads(serial_str) + for obj_dict in serial_list: + ret_list.append(obj_dict["pk"]) + return ret_list + + @staticmethod + def _get_field_values(serial_str, field_name): + ret_list = [] + serial_list = json.loads(serial_str) + for obj_dict in serial_list: + if field_name in obj_dict["fields"]: + ret_list.append(obj_dict["fields"][field_name]) + return ret_list + + def test_indentation_whitespace(self): + Score.objects.create(score=5.0) + Score.objects.create(score=6.0) + qset = Score.objects.all() + + s = serializers.json.Serializer() + json_data = s.serialize(qset, indent=2) + for line in json_data.splitlines(): + if re.search(r'.+,\s*$', line): + self.assertEqual(line, line.rstrip()) + + def test_json_deserializer_exception(self): + with self.assertRaises(DeserializationError): + for obj in serializers.deserialize("json", """[{"pk":1}"""): + pass + + def test_helpful_error_message_invalid_pk(self): + """ + If there is an invalid primary key, the error message should contain + the model associated with it. + """ + test_string = """[{ + "pk": "badpk", + "model": "serializers.player", + "fields": { + "name": "Bob", + "rank": 1, + "team": "Team" + } + }]""" + with self.assertRaisesMessage(DeserializationError, "(serializers.player:pk=badpk)"): + list(serializers.deserialize('json', test_string)) + + def test_helpful_error_message_invalid_field(self): + """ + If there is an invalid field value, the error message should contain + the model associated with it. + """ + test_string = """[{ + "pk": "1", + "model": "serializers.player", + "fields": { + "name": "Bob", + "rank": "invalidint", + "team": "Team" + } + }]""" + expected = "(serializers.player:pk=1) field_value was 'invalidint'" + with self.assertRaisesMessage(DeserializationError, expected): + list(serializers.deserialize('json', test_string)) + + def test_helpful_error_message_for_foreign_keys(self): + """ + Invalid foreign keys with a natural key should throw a helpful error + message, such as what the failing key is. + """ + test_string = """[{ + "pk": 1, + "model": "serializers.category", + "fields": { + "name": "Unknown foreign key", + "meta_data": [ + "doesnotexist", + "metadata" + ] + } + }]""" + key = ["doesnotexist", "metadata"] + expected = "(serializers.category:pk=1) field_value was '%r'" % key + with self.assertRaisesMessage(DeserializationError, expected): + list(serializers.deserialize('json', test_string)) + + def test_helpful_error_message_for_many2many_non_natural(self): + """ + Invalid many-to-many keys should throw a helpful error message. + """ + test_string = """[{ + "pk": 1, + "model": "serializers.article", + "fields": { + "author": 1, + "headline": "Unknown many to many", + "pub_date": "2014-09-15T10:35:00", + "categories": [1, "doesnotexist"] + } + }, { + "pk": 1, + "model": "serializers.author", + "fields": { + "name": "Agnes" + } + }, { + "pk": 1, + "model": "serializers.category", + "fields": { + "name": "Reference" + } + }]""" + expected = "(serializers.article:pk=1) field_value was 'doesnotexist'" + with self.assertRaisesMessage(DeserializationError, expected): + list(serializers.deserialize('json', test_string)) + + def test_helpful_error_message_for_many2many_natural1(self): + """ + Invalid many-to-many keys should throw a helpful error message. + This tests the code path where one of a list of natural keys is invalid. + """ + test_string = """[{ + "pk": 1, + "model": "serializers.categorymetadata", + "fields": { + "kind": "author", + "name": "meta1", + "value": "Agnes" + } + }, { + "pk": 1, + "model": "serializers.article", + "fields": { + "author": 1, + "headline": "Unknown many to many", + "pub_date": "2014-09-15T10:35:00", + "meta_data": [ + ["author", "meta1"], + ["doesnotexist", "meta1"], + ["author", "meta1"] + ] + } + }, { + "pk": 1, + "model": "serializers.author", + "fields": { + "name": "Agnes" + } + }]""" + key = ["doesnotexist", "meta1"] + expected = "(serializers.article:pk=1) field_value was '%r'" % key + with self.assertRaisesMessage(DeserializationError, expected): + for obj in serializers.deserialize('json', test_string): + obj.save() + + def test_helpful_error_message_for_many2many_natural2(self): + """ + Invalid many-to-many keys should throw a helpful error message. This + tests the code path where a natural many-to-many key has only a single + value. + """ + test_string = """[{ + "pk": 1, + "model": "serializers.article", + "fields": { + "author": 1, + "headline": "Unknown many to many", + "pub_date": "2014-09-15T10:35:00", + "meta_data": [1, "doesnotexist"] + } + }, { + "pk": 1, + "model": "serializers.categorymetadata", + "fields": { + "kind": "author", + "name": "meta1", + "value": "Agnes" + } + }, { + "pk": 1, + "model": "serializers.author", + "fields": { + "name": "Agnes" + } + }]""" + expected = "(serializers.article:pk=1) field_value was 'doesnotexist'" + with self.assertRaisesMessage(DeserializationError, expected): + for obj in serializers.deserialize('json', test_string, ignore=False): + obj.save() + + +class JsonSerializerTransactionTestCase(SerializersTransactionTestBase, TransactionTestCase): + serializer_name = "json" + fwd_ref_str = """[ + { + "pk": 1, + "model": "serializers.article", + "fields": { + "headline": "Forward references pose no problem", + "pub_date": "2006-06-16T15:00:00", + "categories": [1], + "author": 1 + } + }, + { + "pk": 1, + "model": "serializers.category", + "fields": { + "name": "Reference" + } + }, + { + "pk": 1, + "model": "serializers.author", + "fields": { + "name": "Agnes" + } + }]""" diff --git a/tests/serializers/tests.py b/tests/serializers/tests.py index c288bf7ab8..ffd573c0cc 100644 --- a/tests/serializers/tests.py +++ b/tests/serializers/tests.py @@ -1,16 +1,13 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals -import json -import re from datetime import datetime from django.core import serializers from django.core.serializers.base import ProgressBar from django.db import connection, transaction from django.test import ( - SimpleTestCase, TestCase, TransactionTestCase, mock, override_settings, - skipUnlessDBFeature, + SimpleTestCase, mock, override_settings, skipUnlessDBFeature, ) from django.test.utils import Approximate from django.utils.six import StringIO @@ -320,259 +317,3 @@ class SerializersTransactionTestBase(object): art_obj = Article.objects.all()[0] self.assertEqual(art_obj.categories.all().count(), 1) self.assertEqual(art_obj.author.name, "Agnes") - - -class JsonSerializerTestCase(SerializersTestBase, TestCase): - serializer_name = "json" - pkless_str = """[ - { - "pk": null, - "model": "serializers.category", - "fields": {"name": "Reference"} - }, { - "model": "serializers.category", - "fields": {"name": "Non-fiction"} - }]""" - mapping_ordering_str = """[ -{ - "model": "serializers.article", - "pk": %(article_pk)s, - "fields": { - "author": %(author_pk)s, - "headline": "Poker has no place on ESPN", - "pub_date": "2006-06-16T11:00:00", - "categories": [ - %(first_category_pk)s, - %(second_category_pk)s - ], - "meta_data": [] - } -} -] -""" - - @staticmethod - def _validate_output(serial_str): - try: - json.loads(serial_str) - except Exception: - return False - else: - return True - - @staticmethod - def _get_pk_values(serial_str): - ret_list = [] - serial_list = json.loads(serial_str) - for obj_dict in serial_list: - ret_list.append(obj_dict["pk"]) - return ret_list - - @staticmethod - def _get_field_values(serial_str, field_name): - ret_list = [] - serial_list = json.loads(serial_str) - for obj_dict in serial_list: - if field_name in obj_dict["fields"]: - ret_list.append(obj_dict["fields"][field_name]) - return ret_list - - def test_indentation_whitespace(self): - Score.objects.create(score=5.0) - Score.objects.create(score=6.0) - qset = Score.objects.all() - - s = serializers.json.Serializer() - json_data = s.serialize(qset, indent=2) - for line in json_data.splitlines(): - if re.search(r'.+,\s*$', line): - self.assertEqual(line, line.rstrip()) - - def test_helpful_error_message_invalid_pk(self): - """ - If there is an invalid primary key, the error message should contain - the model associated with it. - """ - test_string = """[{ - "pk": "badpk", - "model": "serializers.player", - "fields": { - "name": "Bob", - "rank": 1, - "team": "Team" - } - }]""" - with self.assertRaisesMessage(serializers.base.DeserializationError, "(serializers.player:pk=badpk)"): - list(serializers.deserialize('json', test_string)) - - def test_helpful_error_message_invalid_field(self): - """ - If there is an invalid field value, the error message should contain - the model associated with it. - """ - test_string = """[{ - "pk": "1", - "model": "serializers.player", - "fields": { - "name": "Bob", - "rank": "invalidint", - "team": "Team" - } - }]""" - expected = "(serializers.player:pk=1) field_value was 'invalidint'" - with self.assertRaisesMessage(serializers.base.DeserializationError, expected): - list(serializers.deserialize('json', test_string)) - - def test_helpful_error_message_for_foreign_keys(self): - """ - Invalid foreign keys with a natural key should throw a helpful error - message, such as what the failing key is. - """ - test_string = """[{ - "pk": 1, - "model": "serializers.category", - "fields": { - "name": "Unknown foreign key", - "meta_data": [ - "doesnotexist", - "metadata" - ] - } - }]""" - key = ["doesnotexist", "metadata"] - expected = "(serializers.category:pk=1) field_value was '%r'" % key - with self.assertRaisesMessage(serializers.base.DeserializationError, expected): - list(serializers.deserialize('json', test_string)) - - def test_helpful_error_message_for_many2many_non_natural(self): - """ - Invalid many-to-many keys should throw a helpful error message. - """ - test_string = """[{ - "pk": 1, - "model": "serializers.article", - "fields": { - "author": 1, - "headline": "Unknown many to many", - "pub_date": "2014-09-15T10:35:00", - "categories": [1, "doesnotexist"] - } - }, { - "pk": 1, - "model": "serializers.author", - "fields": { - "name": "Agnes" - } - }, { - "pk": 1, - "model": "serializers.category", - "fields": { - "name": "Reference" - } - }]""" - expected = "(serializers.article:pk=1) field_value was 'doesnotexist'" - with self.assertRaisesMessage(serializers.base.DeserializationError, expected): - list(serializers.deserialize('json', test_string)) - - def test_helpful_error_message_for_many2many_natural1(self): - """ - Invalid many-to-many keys should throw a helpful error message. - This tests the code path where one of a list of natural keys is invalid. - """ - test_string = """[{ - "pk": 1, - "model": "serializers.categorymetadata", - "fields": { - "kind": "author", - "name": "meta1", - "value": "Agnes" - } - }, { - "pk": 1, - "model": "serializers.article", - "fields": { - "author": 1, - "headline": "Unknown many to many", - "pub_date": "2014-09-15T10:35:00", - "meta_data": [ - ["author", "meta1"], - ["doesnotexist", "meta1"], - ["author", "meta1"] - ] - } - }, { - "pk": 1, - "model": "serializers.author", - "fields": { - "name": "Agnes" - } - }]""" - key = ["doesnotexist", "meta1"] - expected = "(serializers.article:pk=1) field_value was '%r'" % key - with self.assertRaisesMessage(serializers.base.DeserializationError, expected): - for obj in serializers.deserialize('json', test_string): - obj.save() - - def test_helpful_error_message_for_many2many_natural2(self): - """ - Invalid many-to-many keys should throw a helpful error message. This - tests the code path where a natural many-to-many key has only a single - value. - """ - test_string = """[{ - "pk": 1, - "model": "serializers.article", - "fields": { - "author": 1, - "headline": "Unknown many to many", - "pub_date": "2014-09-15T10:35:00", - "meta_data": [1, "doesnotexist"] - } - }, { - "pk": 1, - "model": "serializers.categorymetadata", - "fields": { - "kind": "author", - "name": "meta1", - "value": "Agnes" - } - }, { - "pk": 1, - "model": "serializers.author", - "fields": { - "name": "Agnes" - } - }]""" - expected = "(serializers.article:pk=1) field_value was 'doesnotexist'" - with self.assertRaisesMessage(serializers.base.DeserializationError, expected): - for obj in serializers.deserialize('json', test_string, ignore=False): - obj.save() - - -class JsonSerializerTransactionTestCase(SerializersTransactionTestBase, TransactionTestCase): - serializer_name = "json" - fwd_ref_str = """[ - { - "pk": 1, - "model": "serializers.article", - "fields": { - "headline": "Forward references pose no problem", - "pub_date": "2006-06-16T15:00:00", - "categories": [1], - "author": 1 - } - }, - { - "pk": 1, - "model": "serializers.category", - "fields": { - "name": "Reference" - } - }, - { - "pk": 1, - "model": "serializers.author", - "fields": { - "name": "Agnes" - } - }]""" diff --git a/tests/serializers_regress/tests.py b/tests/serializers_regress/tests.py index fd05eedc43..e8a7aa359b 100644 --- a/tests/serializers_regress/tests.py +++ b/tests/serializers_regress/tests.py @@ -14,7 +14,6 @@ import uuid from django.core import serializers from django.core.serializers import SerializerDoesNotExist -from django.core.serializers.base import DeserializationError from django.db import connection, models from django.http import HttpResponse from django.test import TestCase, skipUnlessDBFeature @@ -421,11 +420,6 @@ class SerializerTests(TestCase): with self.assertRaises(SerializerDoesNotExist): serializers.get_deserializer("nonsense") - def test_json_deserializer_exception(self): - with self.assertRaises(DeserializationError): - for obj in serializers.deserialize("json", """[{"pk":1}"""): - pass - def test_serialize_proxy_model(self): BaseModel.objects.create(parent_data=1) base_objects = BaseModel.objects.all()