Python 结果相等时单元测试失败
Python unittest failure when results appear equal
我正在 运行对我刚刚组装的 RPN 计算器进行一系列单元测试。这个计算器可以混合使用整数、浮点数和派卡。我经常需要能够使用 picas 来计算我正在做的一些排版工作。
出于某种原因,我的一个单元测试失败了:
Failure
Traceback (most recent call last):
File "/Users/andrew/Developer/pyRpn/test_rpn.py", line 112, in test_pica_subtracted_from_pica
self.assertEqual(self.calc.rpn(['10p3', '2p1', '-']), ['8p2'])
AssertionError: Lists differ: ['8p2'] != ['8p2']
First differing element 0:
'8p2'
8p2
['8p2']
我不明白为什么。为了简化,我将列表从等式中取出并直接与字符串进行比较:
Failure
Expected :'8p2'
Actual :'8p2'
<Click to see difference>
Traceback (most recent call last):
File "/Users/andrew/Developer/pyRpn/test_rpn.py", line 112, in test_pica_subtracted_from_pica
self.assertEqual(self.calc.rpn(['10p3', '2p1', '-']).pop(), '8p2')
AssertionError: '8p2' != '8p2'
还是失败了。我不明白为什么 '8p2' != '8p2'
。 运行 in PyCharm 如果我点击查看不同,它告诉我没有差异,内容相同,但测试失败。它也从命令行失败。
我已经将相同的测试作为 doctest:
"""
>>> RPN().rpn(['10p3', '2p1', '-'])
['8p2']
"""
顺利通过。
MCVE:
import re
import unittest
class Pica(object):
def __init__(self, points):
self.points = points
def __repr__(self):
whole_points = int(self.points / 12)
sub_points = self.points - (whole_points * 12)
return "'%rp%r'" % (whole_points, sub_points)
def __sub__(self, other):
if type(other) is Pica:
return Pica(self.points - other.points)
class RPN:
def __init__(self):
self.oper_dict = {'-': RPN.pop_two_and_sub}
self.pica_pattern = re.compile("(\d+)p(\d+)")
def pop_two_and_sub(self, terms):
terms.append(terms.pop() - terms.pop())
def rpn(self, terms):
result = []
for term in terms:
if term in self.oper_dict:
self.oper_dict[term](self, result)
elif self.pica_pattern.match(term):
match = self.pica_pattern.match(term)
result.append(Pica(int(match.group(1)) * 12 + int(match.group(2))))
else:
raise SyntaxError
return result
class TestPica(unittest.TestCase):
def test_pica_subtracted_from_pica(self):
self.assertCountEqual(RPN().rpn(['2p1', '10p3', '-']), ['8p2'])
if __name__ == '__main__':
unittest.main()
当我 运行 使用 Python 3.5 时,出现以下错误:
Failure
Traceback (most recent call last):
File "/Users/andrew/Developer/pyRpn/mvce.py", line 42, in test_pica_subtracted_from_pica
self.assertCountEqual(RPN().rpn(['2p1', '10p3', '-']), ['8p2'])
AssertionError: Element counts were not equal:
First has 1, Second has 0: '8p2'
First has 0, Second has 1: '8p2'
结果看似相等,但事实并非如此。您不是在比较字符串列表。 rpn()
可以 return 一个包含 Pica
个对象的列表:
>>> from rpn import RPN
>>> type(RPN().rpn(['2p1', '10p3', '-'])[0])
<class 'rpn.Pica'>
这表明由 rpn()
编辑的列表 return 的第一个元素是 Pica
。因此,将 Pica
与字符串进行比较将是 return False
,因此您的断言失败。
您可以将 __eq__()
方法添加到您的 Pica
class,然后您可以将 Pica
s 与 Pica
s 进行比较:
def __eq__(self, other):
"""Test two Pica objects for equality"""
return self.points == other.points
那么你可以在测试中这样做:
self.assertEqual(self.calc.rpn(['10p3', 2, '-']), [Pica(8*12+3)])
如果能够从字符串创建 Pica
就好了:
def __init__(self, value):
if isinstance(value, str):
a,b = value.split('p')
value = int(a) * 12 + int(b)
self.points = value
现在你可以这样测试了:
self.assertEqual(self.calc.rpn(['10p3', 2, '-']), [Pica('8p3')])
好的,我发现了不同之处。 Python 3 对 unicode 的支持更多,但它没有显示打印 unicode 字符串时有效的编码,这就是为什么即使它们具有不同的类型,它们也打印相同的原因:
<class '__main__.Pica'>
<class 'str'>
为了使断言起作用,要么需要更智能的比较,要么在调用断言方法之前将字符串置于通用格式。
我正在 运行对我刚刚组装的 RPN 计算器进行一系列单元测试。这个计算器可以混合使用整数、浮点数和派卡。我经常需要能够使用 picas 来计算我正在做的一些排版工作。
出于某种原因,我的一个单元测试失败了:
Failure
Traceback (most recent call last):
File "/Users/andrew/Developer/pyRpn/test_rpn.py", line 112, in test_pica_subtracted_from_pica
self.assertEqual(self.calc.rpn(['10p3', '2p1', '-']), ['8p2'])
AssertionError: Lists differ: ['8p2'] != ['8p2']
First differing element 0:
'8p2'
8p2
['8p2']
我不明白为什么。为了简化,我将列表从等式中取出并直接与字符串进行比较:
Failure
Expected :'8p2'
Actual :'8p2'
<Click to see difference>
Traceback (most recent call last):
File "/Users/andrew/Developer/pyRpn/test_rpn.py", line 112, in test_pica_subtracted_from_pica
self.assertEqual(self.calc.rpn(['10p3', '2p1', '-']).pop(), '8p2')
AssertionError: '8p2' != '8p2'
还是失败了。我不明白为什么 '8p2' != '8p2'
。 运行 in PyCharm 如果我点击查看不同,它告诉我没有差异,内容相同,但测试失败。它也从命令行失败。
我已经将相同的测试作为 doctest:
"""
>>> RPN().rpn(['10p3', '2p1', '-'])
['8p2']
"""
顺利通过。
MCVE:
import re
import unittest
class Pica(object):
def __init__(self, points):
self.points = points
def __repr__(self):
whole_points = int(self.points / 12)
sub_points = self.points - (whole_points * 12)
return "'%rp%r'" % (whole_points, sub_points)
def __sub__(self, other):
if type(other) is Pica:
return Pica(self.points - other.points)
class RPN:
def __init__(self):
self.oper_dict = {'-': RPN.pop_two_and_sub}
self.pica_pattern = re.compile("(\d+)p(\d+)")
def pop_two_and_sub(self, terms):
terms.append(terms.pop() - terms.pop())
def rpn(self, terms):
result = []
for term in terms:
if term in self.oper_dict:
self.oper_dict[term](self, result)
elif self.pica_pattern.match(term):
match = self.pica_pattern.match(term)
result.append(Pica(int(match.group(1)) * 12 + int(match.group(2))))
else:
raise SyntaxError
return result
class TestPica(unittest.TestCase):
def test_pica_subtracted_from_pica(self):
self.assertCountEqual(RPN().rpn(['2p1', '10p3', '-']), ['8p2'])
if __name__ == '__main__':
unittest.main()
当我 运行 使用 Python 3.5 时,出现以下错误:
Failure
Traceback (most recent call last):
File "/Users/andrew/Developer/pyRpn/mvce.py", line 42, in test_pica_subtracted_from_pica
self.assertCountEqual(RPN().rpn(['2p1', '10p3', '-']), ['8p2'])
AssertionError: Element counts were not equal:
First has 1, Second has 0: '8p2'
First has 0, Second has 1: '8p2'
结果看似相等,但事实并非如此。您不是在比较字符串列表。 rpn()
可以 return 一个包含 Pica
个对象的列表:
>>> from rpn import RPN
>>> type(RPN().rpn(['2p1', '10p3', '-'])[0])
<class 'rpn.Pica'>
这表明由 rpn()
编辑的列表 return 的第一个元素是 Pica
。因此,将 Pica
与字符串进行比较将是 return False
,因此您的断言失败。
您可以将 __eq__()
方法添加到您的 Pica
class,然后您可以将 Pica
s 与 Pica
s 进行比较:
def __eq__(self, other):
"""Test two Pica objects for equality"""
return self.points == other.points
那么你可以在测试中这样做:
self.assertEqual(self.calc.rpn(['10p3', 2, '-']), [Pica(8*12+3)])
如果能够从字符串创建 Pica
就好了:
def __init__(self, value):
if isinstance(value, str):
a,b = value.split('p')
value = int(a) * 12 + int(b)
self.points = value
现在你可以这样测试了:
self.assertEqual(self.calc.rpn(['10p3', 2, '-']), [Pica('8p3')])
好的,我发现了不同之处。 Python 3 对 unicode 的支持更多,但它没有显示打印 unicode 字符串时有效的编码,这就是为什么即使它们具有不同的类型,它们也打印相同的原因:
<class '__main__.Pica'>
<class 'str'>
为了使断言起作用,要么需要更智能的比较,要么在调用断言方法之前将字符串置于通用格式。