1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
|
# encoding: utf-8
# This file is part of py-serializable
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
# Copyright (c) Paul Horton. All Rights Reserved.
import json
import os
from typing import Any, Optional, Union
from unittest import TestCase
import lxml # type: ignore
from defusedxml import ElementTree as SafeElementTree # type: ignore
from xmldiff import main # type: ignore
from xmldiff.actions import MoveNode # type: ignore
FIXTURES_DIRECTORY = os.path.join(os.path.dirname(__file__), 'fixtures')
class BaseTestCase(TestCase):
@staticmethod
def _sort_json_dict(item: object) -> Any:
if isinstance(item, dict):
return sorted((key, BaseTestCase._sort_json_dict(values)) for key, values in item.items())
if isinstance(item, list):
return sorted(BaseTestCase._sort_json_dict(x) for x in item)
else:
return item
def assertEqualJson(self, expected: str, actual: str) -> None:
self.assertEqual(
BaseTestCase._sort_json_dict(json.loads(expected)),
BaseTestCase._sort_json_dict(json.loads(actual))
)
def assertEqualXml(self, expected: str, actual: str) -> None:
a = SafeElementTree.tostring(
SafeElementTree.fromstring(expected, lxml.etree.XMLParser(remove_blank_text=True, remove_comments=True)),
'unicode'
)
b = SafeElementTree.tostring(
SafeElementTree.fromstring(actual, lxml.etree.XMLParser(remove_blank_text=True, remove_comments=True)),
'unicode'
)
diff_results = main.diff_texts(a, b, diff_options={'F': 0.5})
diff_results = list(filter(lambda o: not isinstance(o, MoveNode), diff_results))
self.assertEqual(len(diff_results), 0,
f'There are XML differences: {diff_results!r}\n- {a!s}\n+ {b!s}')
class DeepCompareMixin(object):
def assertDeepEqual(self: Union[TestCase, 'DeepCompareMixin'],
first: Any, second: Any, msg: Optional[str] = None) -> None:
"""costly compare, but very verbose"""
_omd = self.maxDiff
try:
self.maxDiff = None
dd1 = self.__deepDict(first)
dd2 = self.__deepDict(second)
self.assertDictEqual(dd1, dd2, msg)
finally:
self.maxDiff = _omd
def __deepDict(self, o: Any) -> Any:
if isinstance(o, tuple):
return tuple(self.__deepDict(i) for i in o)
if isinstance(o, list):
return list(self.__deepDict(i) for i in o)
if isinstance(o, dict):
return {k: self.__deepDict(v) for k, v in o.items()}
if isinstance(o, set):
# this method returns dict. `dict` is not hashable, so use `tuple` instead.
return tuple(self.__deepDict(i) for i in sorted(o, key=hash)) + ('%conv:%set',)
if hasattr(o, '__dict__'):
d = {a: self.__deepDict(v) for a, v in o.__dict__.items() if '__' not in a}
d['%conv'] = str(type(o))
return d
return o
|