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

dec*_*bot 7 python string testing unit-testing truncated

我正在为我的程序在python中进行单元测试,我想做一个assertEquals测试。

我的代码如下所示:

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

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

任何人都有一个想法如何解决这个问题?

Mar*_*ers 10

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.
Run Code Online (Sandbox Code Playgroud)

在上面的示例中,两个字符串共享一个长前缀,通过用[291 chars]两个前缀替换 291 个字符来缩短该前缀。它们还共享一个很长的后缀,通过将文本替换为[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.
Run Code Online (Sandbox Code Playgroud)

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

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

self.maxDiff = None
Run Code Online (Sandbox Code Playgroud)

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

AssertionError的: 'foof [231个字符] oofoofoofoofoofoofoofoofoofoofoofoofoofoofoofo [315个字符] ofoo'= 'foof [231个字符] oofoobarbarbarbarbarbarbarbarbarbarbarbarbarba [285个字符] ofoo' - foofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoo!?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ + foofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoobarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarfoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoo?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

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

from textwrap import wrap

self.maxDiff = None
self.assertEquals(wrap(parser), wrap("some long string"), "String is not equal")
Run Code Online (Sandbox Code Playgroud)

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

>>> 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']
Run Code Online (Sandbox Code Playgroud)


pts*_*pts 9

要替换[... 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
Run Code Online (Sandbox Code Playgroud)

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

  • 谢谢你,所有其他答案都指向“maxDiff = None”,这没有帮助。 (2认同)

小智 6

所以,我进入了这个问题,因为我遇到了一个问题,即我使用assertEqual()和'self.maxDiff = None'不会导致显示完整的输出。追溯到原来,因为两个对象的类型不同(一个是列表,一个是生成器),所以没有使用会利用'self.maxDiff'的代码路径。因此,如果遇到需要完整的diff且'self.maxDiff'无法正常工作的问题,请确保两个比较对象的类型相同。

  • 更糟糕的是,差异渲染可能会让它们看起来像是同一类型,但实际上并非如此。测试序列化器时,您会得到“OrderedDict”而不是“dict”,因此比较这两个“self.maxDiff”没有效果。你必须做`self.assertEqual(dict(result),expected_result))` (2认同)
  • 这并不试图回答最初的问题:如果两个字符串不同,如何获取两个字符串的完整转储(不缩短)。 (2认同)