python - 如何正确覆盖 TestCase.assertEqual(),产生正确的堆栈跟踪?
问题描述
我正在尝试为Continuing in Python's unittest when an assertion failed实现一个干净的答案。
我想改进投票最多和不被接受的答案:https ://stackoverflow.com/a/5028110/4934640
我有这个答案的问题是它迫使我try...catch
在我的单元测试中使用。然后,我试图将try...catch
逻辑封装在方法的覆盖中TestCase.assertEqual
。
到目前为止,一切都很好。我设法覆盖了该TestCase.assertEqual
方法,但是,提供的堆栈跟踪是错误的。
运行以下最小示例:
import unittest
import traceback
class MultipleAssertionFailures(unittest.TestCase):
def __init__(self, *args, **kwargs):
self.verificationErrors = []
super(MultipleAssertionFailures, self).__init__( *args, **kwargs )
def tearDown(self):
super(MultipleAssertionFailures, self).tearDown()
if self.verificationErrors:
self.fail( '\n\n' + '\n'.join( self.verificationErrors ) )
self.verificationErrors.clear()
def assertEqual(self, goal, results, msg=""):
try:
super( MultipleAssertionFailures, self ).assertEqual( goal, results, msg )
except unittest.TestCase.failureException as error:
stacktrace = traceback.format_exc()
# stacktrace = traceback.format_stack()
self.verificationErrors.append( "".join( stacktrace ) )
# class DummyTestCase(unittest.TestCase):
class DummyTestCase(MultipleAssertionFailures):
def setUp(self):
self.maxDiff = None
super(DummyTestCase, self).setUp()
def tearDown(self):
super(DummyTestCase, self).tearDown()
def test_function_name(self):
self.assertEqual( "var", "bar" )
self.assertEqual( "1937", "511" )
if __name__ == '__main__':
unittest.main()
你得到以下输出:
F
======================================================================
FAIL: test_function_name (__main__.DummyTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "D:\User\Downloads\test.py", line 36, in tearDown
super(DummyTestCase, self).tearDown()
File "D:\User\Downloads\test.py", line 15, in tearDown
self.fail( '\n\n' + '\n'.join( self.verificationErrors ) )
AssertionError:
Traceback (most recent call last):
File "D:\User\Downloads\test.py", line 21, in assertEqual
super( MultipleAssertionFailures, self ).assertEqual( goal, results, msg )
File "F:\Python\lib\unittest\case.py", line 844, in assertEqual
assertion_func(first, second, msg=msg)
File "F:\Python\lib\unittest\case.py", line 1228, in assertMultiLineEqual
self.fail(self._formatMessage(msg, standardMsg))
File "F:\Python\lib\unittest\case.py", line 685, in fail
raise self.failureException(msg)
AssertionError: 'var' != 'bar'
- var
? ^
+ bar
? ^
:
Traceback (most recent call last):
File "D:\User\Downloads\test.py", line 21, in assertEqual
super( MultipleAssertionFailures, self ).assertEqual( goal, results, msg )
File "F:\Python\lib\unittest\case.py", line 844, in assertEqual
assertion_func(first, second, msg=msg)
File "F:\Python\lib\unittest\case.py", line 1228, in assertMultiLineEqual
self.fail(self._formatMessage(msg, standardMsg))
File "F:\Python\lib\unittest\case.py", line 685, in fail
raise self.failureException(msg)
AssertionError: '1937' != '511'
- 1937
+ 511
:
在输出中,您会注意到两个显示的堆栈跟踪是错误的,因为它们不反映单元测试代码的位置,而只反映我的断言代码所在的位置。通过在最小示例上注释class DummyTestCase(MultipleAssertionFailures)
和取消注释class DummyTestCase(unittest.TestCase)
,您将看到堆栈跟踪的正确输出应该如何:
F
======================================================================
FAIL: test_function_name (__main__.DummyTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "D:\User\Downloads\test.py", line 39, in test_function_name
self.assertEqual( "var", "bar" )
AssertionError: 'var' != 'bar'
- var
? ^
+ bar
? ^
此堆栈跟踪(内置堆栈跟踪)正确指向test.py", line 39, in test_function_name
. 我尝试查看TestCase
模块,但我无法弄清楚它是如何设法产生这个有意义的堆栈跟踪的。
或者,取消注释该行stacktrace = traceback.format_exc()
,我们可以获得一个非常完整的堆栈跟踪:
F
======================================================================
FAIL: test_function_name (__main__.DummyTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "D:\User\Downloads\test.py", line 36, in tearDown
super(DummyTestCase, self).tearDown()
File "D:\User\Downloads\test.py", line 15, in tearDown
self.fail( '\n\n' + '\n'.join( self.verificationErrors ) )
AssertionError:
File "D:\User\Downloads\test.py", line 43, in <module>
unittest.main()
File "F:\Python\lib\unittest\main.py", line 101, in __init__
self.runTests()
File "F:\Python\lib\unittest\main.py", line 271, in runTests
self.result = testRunner.run(self.test)
File "F:\Python\lib\unittest\runner.py", line 176, in run
test(result)
File "F:\Python\lib\unittest\suite.py", line 84, in __call__
return self.run(*args, **kwds)
File "F:\Python\lib\unittest\suite.py", line 122, in run
test(result)
File "F:\Python\lib\unittest\suite.py", line 84, in __call__
return self.run(*args, **kwds)
File "F:\Python\lib\unittest\suite.py", line 122, in run
test(result)
File "F:\Python\lib\unittest\case.py", line 668, in __call__
return self.run(*args, **kwds)
File "F:\Python\lib\unittest\case.py", line 620, in run
testMethod()
File "D:\User\Downloads\test.py", line 39, in test_function_name
self.assertEqual( "var", "bar" )
File "D:\User\Downloads\test.py", line 25, in assertEqual
stacktrace = traceback.format_stack()
File "D:\User\Downloads\test.py", line 43, in <module>
unittest.main()
File "F:\Python\lib\unittest\main.py", line 101, in __init__
self.runTests()
File "F:\Python\lib\unittest\main.py", line 271, in runTests
self.result = testRunner.run(self.test)
File "F:\Python\lib\unittest\runner.py", line 176, in run
test(result)
File "F:\Python\lib\unittest\suite.py", line 84, in __call__
return self.run(*args, **kwds)
File "F:\Python\lib\unittest\suite.py", line 122, in run
test(result)
File "F:\Python\lib\unittest\suite.py", line 84, in __call__
return self.run(*args, **kwds)
File "F:\Python\lib\unittest\suite.py", line 122, in run
test(result)
File "F:\Python\lib\unittest\case.py", line 668, in __call__
return self.run(*args, **kwds)
File "F:\Python\lib\unittest\case.py", line 620, in run
testMethod()
File "D:\User\Downloads\test.py", line 40, in test_function_name
self.assertEqual( "1937", "511" )
File "D:\User\Downloads\test.py", line 25, in assertEqual
stacktrace = traceback.format_stack()
我怎么能总是把这个完整的堆栈跟踪切断成像内置TestCase.assertEqual
函数那样有意义的东西?
解决方案
推荐阅读
- odata - 使用 Lucene 查询语法的 Azure 搜索查询是否可以有一个带有 geo.distance 函数和另一个过滤条件的过滤器?
- java - BigDecimal 除数不四舍五入
- javascript - AJAX code returns error of "Column cannot be null" for PHP Session variable
- php - Find a substring inside a string with special characters PHP
- scala - 如何使用未转义的分隔符分隔带有分隔符的字符串
- amazon-web-services - API Gateway 中的 URL 路径参数未映射到事件
- excel - VBA xmlhttprequest 循环而不关闭连接
- android - 完全隐藏的 APK 问题
- java - 输出流持久性问题
- android - Google Admob 和 Firebase with Analytics 需要哪些权限?