我正在用 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 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.
这里,常见的后缀开始有所不同,但差异的开始仍然可见,应该可以帮助您找出文本出了问题的地方。
TestCase.maxDiff
属性设置为更大的数字(默认为8 * 80,80行文本),或者将其设置为None
以完全消除:
self.maxDiff = None
请注意,除非您的字符串包含 newlines,否则差异可能不可读:
断言错误:'foof[231 字符]oofoofoofoofoofoofoofoofoofoofoofoofoofoofoofo[315 个字符]ofoo' != 'foof[231 个字符]oofoobarbarbarbarbarbarbarbarbarbarbarbarba[285 字符]ofoo' - foofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoo foofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoo ?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^ + foofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoobarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarfoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoo foofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoo ?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
在这种情况下,换行您的输入和输出文本可能更有用:
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']
看起来“限制”是硬编码在 teamcity/diff_tools.py 中。
def can_be_serialized(self):
...
return len(self.actual) + len(self.expected) < 10000
现在我修补了幻数 10000,它可以工作,但显然不是通用解决方案。我可以考虑提出变更请求,以获得合适的 API。