Python-deepdiff断言
DeepDiff模块常用来效验两个对象是否一致,并找出其中差异之处:
- DeepDiff:字典,可迭代项,字符串和其他对象的深层差异。它将递归查找所有更改。
- DeepSearch:在其它对象在搜索对象
- DeepHash:根据对的内容对其进行哈希处理
- 官网地址:https://deepdiff.readthedocs.io/en/latest/
- 本文只介绍DeepDiff的使用
下载
pip install deepdiff==4.3.2
DeepDiff使用
DeepDiff可以用来校验多种类型的文件内容,例如:txt、json、图片等
校验:txt文件
场景1:a和b两个文件中内容都相同
a.txt 内容:python入门学习
b.txt 内容: python入门学习
相同输出:{}空字典,可以通过空字典进行判断
from deepdiff import DeepDiff
f1, f2 = open("a", "r", encoding="utf-8").read(), open("b", "r", encoding="utf-8").read()
print(DeepDiff(f1, f2))
#相同输出:{}
场景2:
a和b两个文件中内容不相同
a.txt 内容:python学习,django学习
b.txt 内容: python入门学习
from deepdiff import DeepDiff
f1, f2 = open("a", "r", encoding="utf-8").read(), open("b", "r", encoding="utf-8").read()
print(DeepDiff(f1, f2))
当两个文件内容中存在不同时,输出如下:
{'values_changed': {'root': {'new_value': 'python入门学习', 'old_value': 'python学习,django学习'}}}
通过是否有values_changed来判断不同,root中列出了那些内容不相同。
校验:json文件
a.json文件内容
{
"title": "V2EX",
"slogan": "way to explore",
"description": "创意工作者们的社区",
"domain": {
"url": "www.v2ex.com",
"host": "8080"
},
"data": [
{
"id": "5e4fa8531225c9423dcda9d8",
"author_id": "51f0f267f4963ade0e08f503", # b.json中对应位置没有该字段
"tab": "share"
},
{
"id": "5e16978581adfe260207a8c1",
"author_id": "54009f5ccd66f2eb37190485",
"tab": "share"
}
]
}
b.json
{
"title": "2VEX",
"slogan": "way to explore",
"description": "创意工作者们的社区",
"domain": {
"url": "www.v2ex.com",
"host": "8080"
},
"data": [
{
"id": "5e4fa8531225c9423dcda9d8",
"tab": "share"
},
{
"id": "5e16978581adfe260207a8c1",
"author_id": "54009f5ccd66f2eb37190485",
"tab": "share_we"
}
]
}
示例:
import json
from deepdiff import DeepDiff
f1, f2 = json.loads(open("a.json", "r", encoding="utf-8").read()), json.loads(
open("b.json", "r", encoding="utf-8").read())
print(DeepDiff(f1, f2))
输出:
{
'dictionary_item_removed': [root['data'][0]['author_id']], # a中有该字段,b中没有该字段就会出现dictionary_item_removed字段和详细信息
'values_changed': { # 提示字段中有值不一样
"root['data'][1]['tab']": {
'new_value': 'share_we',
'old_value': 'share'
},
"root['title']": {
'new_value': '2VEX',
'old_value': 'V2EX'
}
}
}
校验字典
d1 = {"a": 1, "b": 2, "c": 3, "e": {"a": 3}}
d2 = {"a": 1, "b": 2, "c": 3, "d": 4, "e": {"a": 1}}
print(DeepDiff(d1, d2))
输出:
{
'dictionary_item_added': [root['d']], # b2中有字段和值,b1中没有会出现。
'values_changed': { # d1和d2中都有的字段,值不相同
"root['e']['a']": {
'new_value': 1,
'old_value': 3
}
}
}
总结:当对比的两个对象中,字段只在一个里面有,另外一个没有时输出:
例如:a和b b中有的字段a中没有,输出:dictionary_item_added:{}
a和b a中有的字段b中没有,输出:dictionary_item_removed:{}
当两个对象中都存在,只是值不相同时,输出:values_changed:{}
DeepDiff在单元测试中的应用
import unittest
import requests
from deepdiff import DeepDiff
class MyCase(unittest.TestCase):
expect = {
"title": "V2EX",
"slogan": "way to explore",
"description": "创意工作者们的社区",
"domain": "www.v2ex.com"
}
@classmethod
def setUpClass(cls):
cls.response = requests.get('https://www.v2ex.com/api/site/info.json').json()
def test_case_01(self):
"""成功"""
self.assertEqual(DeepDiff(self.response, self.expect), {})
def test_case_02(self):
"""失败"""
self.assertEqual(DeepDiff(self.response['title'], 'v2ex'), {})
"""
AssertionError: {'values_changed': {'root': {'new_value': 'v2ex', 'old_value': 'V2EX'}}} != {}
"""
if __name__ == '__main__':
unittest.main()
pytest中应用
import pytest
import requests
from deepdiff import DeepDiff
class TestCase:
expect = {
"title": "V2EX",
"slogan": "way to explore",
"description": "创意工作者们的社区",
"domain": "www.v2ex.com"
}
def setup_class(self):
self.response = requests.get('https://www.v2ex.com/api/site/info.json').json()
def test_case_01(self):
assert not DeepDiff(self.response, self.expect)
def test_case_02(self):
assert not DeepDiff(self.response['title'], 'v2ex')
"""
self = <temp.TestCase object at 0x00000272F7B6FE10>
def test_case_02(self):
> assert not DeepDiff(self.response['title'], 'v2ex')
AssertionError: {'values_changed': {'root': {'new_value': 'v2ex', 'old_value': 'V2EX'}}} != {}
E AssertionError: assert not {'values_changed': {'root': {'new_value': 'v2ex', 'old_value': 'V2EX'}}}
E + where {'values_changed': {'root': {'new_value': 'v2ex', 'old_value': 'V2EX'}}} = DeepDiff('V2EX', 'v2ex')
temp.py:104: AssertionError
"""
if __name__ == '__main__':
pytest.main(['-v', __file__])