unittest.TestCase
在Python 2中有一个assertCountEqual
method(assertItemsEqual
,可以说是一个更好的名字),它比较两个迭代并检查它们是否包含相同数量的相同对象,不顾他们的命令。
pytest是否提供类似的东西?所有明显的替代方案(例如,文档中提到的每侧调用set(x)
,sorted(x)
或Counter(list(x))
)都不起作用,因为我要比较的是字典列表,字典不可用。
答案 0 :(得分:3)
pytest不提供assertCountEqual
,但我们可以只使用unittest&#39>
import unittest
def test_stuff():
case = unittest.TestCase()
a = [{'a': 1}, {'b': 2}]
b = [{'b': 2}]
case.assertCountEqual(a, b)
输出也很不错
$ py.test
============================= test session starts ==============================
platform linux -- Python 3.6.2, pytest-3.2.1, py-1.4.34, pluggy-0.4.0
rootdir: /home/they4kman/.virtualenvs/tmp-6626234b42fb350/src, inifile:
collected 1 item
test_stuff.py F
=================================== FAILURES ===================================
__________________________________ test_stuff __________________________________
def test_stuff():
case = unittest.TestCase()
a = [{'a': 1}, {'b': 2}]
b = [{'b': 2}]
> case.assertCountEqual(a, b)
test_stuff.py:7:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/usr/lib/python3.6/unittest/case.py:1182: in assertCountEqual
self.fail(msg)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <unittest.case.TestCase testMethod=runTest>
msg = "Element counts were not equal:\nFirst has 1, Second has 0: {'a': 1}"
def fail(self, msg=None):
"""Fail immediately, with the given message."""
> raise self.failureException(msg)
E AssertionError: Element counts were not equal:
E First has 1, Second has 0: {'a': 1}
/usr/lib/python3.6/unittest/case.py:670: AssertionError
=========================== 1 failed in 0.07 seconds ==========================
附注:the implementation of assertCountEqual
包含针对不可用类型的分支具体,does a bunch of bookkeeping and compares each item with every other item。
答案 1 :(得分:0)
您可以创建一个适用于大多数情况的通用辅助函数:
def items_equal(xs, ys):
if isinstance(xs, dict) and isinstance(ys, dict):
if len(xs) != len(ys):
return False
for key in xs.keys():
try:
if not items_equal(xs[key], ys[key]):
return False
except KeyError:
return False
return True
elif isinstance(xs, list) and isinstance(ys, list):
if len(xs) != len(ys):
return False
sxs = xs
sys = ys
try:
sxs = sorted(xs)
sys = sorted(ys)
for x, y in zip(sxs, sys):
if not items_equal(x, y):
return False
except TypeError:
ys_copy = ys.copy()
for x in xs:
matches = [i for i, y in enumerate(ys_copy) if items_equal(x, y)]
if len(matches):
del ys_copy[matches[0]]
continue
else:
return False
return True
else:
return xs == ys