如何防止在单元测试 python 中截断字符串



我正在为我的程序做一个Python单元测试,我想做一个assertEquals测试。

我的代码看起来像这样:

class UnitTest(unittest.TestCase):
def test_parser(self):
self.assertEquals(parser,"some long string", "String is not equal")

但是,由于我的字符串太长,我得到了类似testing[471 chars]0 != testing[473 chars].我想看看两个字符串之间的确切区别是什么,而不是看到截断的字符串。

有人知道如何解决这个问题吗?

要将[... chars][truncated]...替换为实际字符(无论多长时间,也无论比较值的类型如何),请将以下内容添加到*_test.py文件中:

if 'unittest.util' in __import__('sys').modules:
# Show full diff in self.assertEqual.
__import__('sys').modules['unittest.util']._MAX_LENGTH = 999999999

事实上,正如其他答案所指出的那样,设置self.maxDiff = None无济于事,也不会使[... chars]消失。但是,此设置有助于显示其他类型的长差异,因此我的建议是同时执行这两项操作。

所以,我之所以提出这个问题,是因为我遇到了一个问题,即我正在使用assertEqual()并且self.maxDiff = None不会导致显示完整的输出。通过跟踪,结果发现由于两个对象的类型不同(一个是列表,一个是生成器),因此不使用使用self.maxDiff的代码路径。因此,如果您遇到需要完整差异并且self.maxDiff不起作用的问题,请确保两个比较对象的类型相同。

unittest.TestCase.assertEquals试图为您提供字符串的实际差异,同时使文本适合您的屏幕

为此,它会截断公共部分,因此没有差异的部分通过用[<count> chars]块替换它们来截断它们:

>>> case.assertEqual('foo' * 200, 'foo' * 100 + 'bar' + 'foo' * 99)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/mjpieters/Development/Library/buildout.python/parts/opt/lib/python3.6/unittest/case.py", line 821, in assertEqual
assertion_func(first, second, msg=msg)
File "/Users/mjpieters/Development/Library/buildout.python/parts/opt/lib/python3.6/unittest/case.py", line 1194, in assertMultiLineEqual
self.fail(self._formatMessage(msg, standardMsg))
File "/Users/mjpieters/Development/Library/buildout.python/parts/opt/lib/python3.6/unittest/case.py", line 666, in fail
raise self.failureException(msg)
AssertionError: 'foof[291 chars]oofoofoofoofoofoofoofoofoofoofoofoofoofoofoofo[255 chars]ofoo' != 'foof[291 chars]oofoobarfoofoofoofoofoofoofoofoofoofoofoofoofo[255 chars]ofoo'
Diff is 1819 characters long. Set self.maxDiff to None to see it.

在上面的示例中,两个字符串共享一个长前缀,通过在两个前缀中将 291 个字符替换为[291 chars]来缩短该前缀。它们还共享一个长后缀,通过在两个位置用[255 chars]替换文本再次缩短。

实际差异仍在显示,就在中间。

当然,当你把这个差异做得太长时,甚至差异也会被截断:

>>> case.assertEqual('foo' * 200, 'foo' * 80 + 'bar' * 30 + 'foo' * 80)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/mjpieters/Development/Library/buildout.python/parts/opt/lib/python3.6/unittest/case.py", line 821, in assertEqual
assertion_func(first, second, msg=msg)
File "/Users/mjpieters/Development/Library/buildout.python/parts/opt/lib/python3.6/unittest/case.py", line 1194, in assertMultiLineEqual
self.fail(self._formatMessage(msg, standardMsg))
File "/Users/mjpieters/Development/Library/buildout.python/parts/opt/lib/python3.6/unittest/case.py", line 666, in fail
raise self.failureException(msg)
AssertionError: 'foof[231 chars]oofoofoofoofoofoofoofoofoofoofoofoofoofoofoofo[315 chars]ofoo' != 'foof[231 chars]oofoobarbarbarbarbarbarbarbarbarbarbarbarbarba[285 chars]ofoo'
Diff is 1873 characters long. Set self.maxDiff to None to see it.

在这里,常见的后缀开始有所不同,但差异的开始仍然可见,并且应该可以帮助您找出文本出错的地方。

如果这还不够,您可以增加或消除差异限制。将TestCase.maxDiff属性设置为更大的数字(默认值为 8 * 80,80 行文本),或将其设置为None以完全消除:

self.maxDiff = None

请注意,除非您的字符串包含换行符,否则差异可能无法读取:

断言错误: 'foof[231 chars]oofoofoofo != 'foof[231 chars]oofoobarbarbarbarbarbarbarba[285 查尔斯]奥福' - foofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoo呜�� ?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +foofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoobarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarfoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofo ?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

在这种情况下,包装输入和输出文本可能更有用:

from textwrap import wrap
self.maxDiff = None
self.assertEquals(wrap(parser), wrap("some long string"), "String is not equal")

只是为了让你得到更好、更易读的差异输出:

>>> from textwrap import wrap
>>> case.assertEqual(wrap('foo' * 200), wrap('foo' * 80 + 'bar' * 30 + 'foo' * 80))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/mjpieters/Development/Library/buildout.python/parts/opt/lib/python3.6/unittest/case.py", line 821, in assertEqual
assertion_func(first, second, msg=msg)
File "/Users/mjpieters/Development/Library/buildout.python/parts/opt/lib/python3.6/unittest/case.py", line 1019, in assertListEqual
self.assertSequenceEqual(list1, list2, msg, seq_type=list)
File "/Users/mjpieters/Development/Library/buildout.python/parts/opt/lib/python3.6/unittest/case.py", line 1001, in assertSequenceEqual
self.fail(msg)
File "/Users/mjpieters/Development/Library/buildout.python/parts/opt/lib/python3.6/unittest/case.py", line 666, in fail
raise self.failureException(msg)
AssertionError: Lists differ: ['foo[244 chars]oofoofoofoofoofoofoofoofoofoofoofoofoofoofoof'[336 chars]foo'] != ['foo[244 chars]oofoobarbarbarbarbarbarbarbarbarbarbarbarbarb'[306 chars]foo']
First differing element 3:
'foofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoof'
'foofoofoofoofoofoofoofoofoofoobarbarbarbarbarbarbarbarbarbarbarbarbarb'
['foofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoof',
'oofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofo',
'ofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoo',
-  'foofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoof',
-  'oofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofo',
+  'foofoofoofoofoofoofoofoofoofoobarbarbarbarbarbarbarbarbarbarbarbarbarb',
+  'arbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarfoofoofoofoofoofoofo',
'ofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoo',
'foofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoof',
'oofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofo',
-  'ofoofoofoofoofoofoofoofoofoofoofoofoofoo']
+  'ofoofoofoo']

最新更新