这是一个相当无用的断言错误;它不会告诉所涉及的表达式的值(假设使用的常量实际上是变量名):
$ python -c "assert 6-(3*2)"
[...]
AssertionError
Python中有更好的assert
实现吗?-O
它不能在执行过程中引入额外的开销(除非断言失败)......并且如果使用标志,则必须关闭。
编辑:我知道断言的第二个参数是一个字符串。我不想写一个 .. 因为它被编码在被断言的表达式中。干燥(不要重复自己)。
这是一个相当无用的断言错误;它不会告诉所涉及的表达式的值(假设使用的常量实际上是变量名):
$ python -c "assert 6-(3*2)"
[...]
AssertionError
Python中有更好的assert
实现吗?-O
它不能在执行过程中引入额外的开销(除非断言失败)......并且如果使用标志,则必须关闭。
编辑:我知道断言的第二个参数是一个字符串。我不想写一个 .. 因为它被编码在被断言的表达式中。干燥(不要重复自己)。
正如@Mark Rushakoff 所说 nose
,可以评估失败的断言。它也适用于标准assert
。
# test_error_reporting.py
def test():
a,b,c = 6, 2, 3
assert a - b*c
nosetests
' 帮助:
$ nosetests --help|grep -B2 assert
-d, --detailed-errors, --failure-detail
Add detail to error output by attempting to evaluate
failed asserts [NOSE_DETAILED_ERRORS]
例子:
$ nosetests -d
F
======================================================================
FAIL: test_error_reporting.test
----------------------------------------------------------------------
Traceback (most recent call last):
File "..snip../site-packages/nose/case.py", line 183, in runTest
self.test(*self.arg)
File "..snip../test_error_reporting.py", line 3, in test
assert a - b*c
AssertionError:
6,2,3 = 6, 2, 3
>> assert 6 - 2*3
----------------------------------------------------------------------
Ran 1 test in 0.089s
FAILED (failures=1)
您可以将消息附加到assert
:
assert 6-(3*2), "always fails"
消息也可以动态构建:
assert x != 0, "x is not equal to zero (%d)" % x
有关更多信息,请参阅Python 文档中的assert
语句。
但是,AFAICT,您必须调用他们的断言来进行自省:
import nose
def test1():
nose.tools.assert_equal(6, 5+2)
结果是
C:\temp\py>C:\Python26\Scripts\nosetests.exe -d test.py F ==================================================== ===================== 失败:test.test1 -------------------------------------------------- -------------------- 回溯(最近一次通话最后): 文件“C:\Python26\lib\site-packages\nose-0.11.1-py2.6.egg\nose\case.py”,行 183,在运行测试中 self.test(*self.arg) 文件“C:\temp\py\test.py”,第 3 行,在 test1 鼻子.tools.assert_equal(6, 5+2) 断言错误:6!= 7 >> 引发 self.failureException,\ (无或 '%r != %r' % (6, 7))
注意那里的 AssertionError。当我的线路只是assert 6 == 5+2
时,我会得到:
C:\temp\py>C:\Python26\Scripts\nosetests.exe -d test.py F ==================================================== ===================== 失败:test.test1 -------------------------------------------------- -------------------- 回溯(最近一次通话最后): 文件“C:\Python26\lib\site-packages\nose-0.11.1-py2.6.egg\nose\case.py”,行 183,在运行测试中 self.test(*self.arg) 文件“C:\temp\py\test.py”,第 2 行,在 test1 断言 6 == 5 + 2 断言错误: >> 断言 6 == 5 + 2
另外,我不确定他们的断言是否被跳过-O
,但这将是一个非常快速的检查。
我编写了一个替代代码sys.excepthook
(对任何未处理的异常都调用它),它比标准的要花哨一些。它将分析发生异常的行并打印该行中引用的所有变量(它不会打印所有局部变量,因为这可能会产生太多噪音——而且,重要的变量可能是全局变量)。
我称它为 py_better_exchook(完美的名字),它就在这里。
示例文件:
a = 6
def test():
unrelated_var = 43
b,c = 2, 3
assert a - b*c
import better_exchook
better_exchook.install()
test()
输出:
$ python test_error_reporting.py
EXCEPTION
Traceback (most recent call last):
File "test_error_reporting.py", line 12, in <module>
line: test()
locals:
test = <local> <function test at 0x7fd91b1a05f0>
File "test_error_reporting.py", line 7, in test
line: assert a - b*c
locals:
a = <global> 6
b = <local> 2
c = <local> 3
AssertionError
还有一些其他选择:
from IPython.core import ultratb; sys.excepthook = ultratb.VerboseTB()
。听起来您真正想要做的是在 之前设置一个调试器断点,assert
并根据您喜欢的调试器进行检查。
向您的断言添加一条消息,如果断言失败,将显示该消息:
$ python -c "assert 6-(3*2), '6-(3*2)'"
Traceback (most recent call last):
File "<string>", line 1, in <module>
AssertionError: 6-(3*2)
我能想到的自动提供此功能的唯一方法是将断言包含在过程调用中,然后检查堆栈以获取该行的源代码。不幸的是,额外的调用会在测试中引入开销,并且不会被禁用-O
。