我有一个字典项目列表,我想比较字典列表中的特定键。我正在尝试以下代码,它工作正常,但我看到代码重复。无论如何我可以优化代码吗?
我的数据结构如下
[{
"title": "x86_64",
"type": "info",
"list_type": ["2016-9131", "2016-9147", "2016-9444"]
}, {
"title": "x_64",
"type": "info",
"list_type": ["2036-9131", "2026-9147", "2046-9444"],
}
]
下面是Python代码
import json,pytest
with open('expected_resuts.json') as expected_result:
expected_results=json.load(expected_result)
with open('actual_results.json') as actual_result:
actual_results=json.load(actual_result)
expected_title_list=[]
expected_title_list=[]
expected_name=[]
actual_name=[]
for item in expected_results:
expected_title_list.append(item['title'])
for item in actual_results:
expected_title_list.append(item['title'])
for item in expected_results:
expected_name.append(item['type'])
for item in actual_results:
actual_name.append(item['type'])
def test_title_list():
assert expected_title_list==expected_title_list
def test_name():
assert actual_name==expected_name
仅通过使用列表推导式就可以大大改进它。您还可以在需要它的测试中移动像
expected_vpk_list
这样的变量(以避免创建太多全局变量)。下面的例子:
import json, pytest
with open('expected_results.json') as expected_result:
expected_results = json.load(expected_result)
with open('actual_results.json') as actual_result:
actual_results = json.load(actual_result)
def test_vpk_list():
expected_vpk_list = [result['vpk'] for result in expected_results]
actual_vpk_list = [result['vpk'] for result in actual_results]
assert actual_vpk_list == expected_vpk_list
def test_patch_title():
expected_patch_title = [result['patchTitle'] for result in expected_results]
actual_patch_title = [result['patchTitle'] for result in actual_results]
assert actual_patch_title == expected_patch_title
更新: 这些测试可以通过使用parametrize来合并,如下所示:
@pytest.mark.parametrize('key', [
'vpk',
'patchTitle',
])
def test_key_from_results(key):
expected_values = [result[key] for result in expected_results]
actual_values = [result[key] for result in actual_results]
assert expected_values == actual_values
我最终创建了一个可以在任何地方使用的函数。
def values_match(target: dict, values: dict) -> bool:
"""
Compares values of two dicts match for certain keys only.
"""
return all(target.get(k, Undefined) == v for k, v in values.items())
然后一个仅用于测试:
def assert_values_match(target: dict, values: dict) -> None:
"""
Asserts values of two dicts match for certain keys only.
"""
if not values_match(target, values):
raise AssertionError(
"Values do not match!"
"\nTarget:"
f"\n{format_dict(target)}"
"\nValues:"
f"\n{format_dict(values)}"
)
所以如果我的测试失败:
def test_values_match():
assert_values_match({'a': 2}, {'b': 2})
我得到:
AssertionError: Values do not match!
Target:
{'a': 2}
Values:
{'b': 2}
你可能已经注意到我在上面使用了
Undefined
,这显然不是 Python 中的东西,但对于描述丢失的数据很有用,而你不能用 None
来做到这一点。
您可以像这样创建您的
Undefined
值:
class _UndefinedCls:
def __repr__(self):
return "Undefined"
Undefined = _UndefinedCls()
未定义在这里有两个用途:
所以这就过去了:
def test_values_match():
assert_values_match({'a': 2}, {'a': 2, 'b': Undefined})
但这不是:
def test_values_match():
assert_values_match({'a': 2, 'b': None}, {'a': 2, 'b': Undefined})