我有一个标准unittest格式的测试模块
class my_test(unittest.TestCase):
def test_1(self):
[tests]
def test_2(self):
[tests]
etc....
我的公司有一个专有的测试工具,它将我的模块作为命令行脚本执行,它将捕获我的模块引发的任何错误,但要求我的模块在成功时静音。
所以,我试图找到一种方法来裸露运行我的测试模块,这样如果我的所有测试都通过,那么屏幕上什么都没有打印出来,如果测试因AssertionError而失败,那么该错误会通过标准传递Python错误堆栈(就像普通Python脚本中的任何其他错误一样。)
使用unittest.main()函数的docs拥护者在给定模块中运行所有测试,如
if __name__ == "__main__":
unittest.main()
问题在于,这将测试结果包含在unittest的线束中,因此即使所有测试都成功,它仍然会在屏幕上打印出一些绒毛,如果有错误,它不会被简单地转储为通常的python错误,还穿着马具。
我尝试使用
将输出重定向到备用流with open('.LOG','a') as logf:
suite = unittest.TestLoader().loadTestsFromTestCase(my_test)
unittest.TextTestRunner(stream = logf).run(suite)
这里的问题是EVERYTHING被传送到日志文件(包括所有错误通知)。因此,当我的公司利用运行该模块时,它就会成功完成,因为就其所知,没有引发任何错误(因为它们都是通过管道传输到日志文件中)。
关于如何构建一个能够抑制所有漏洞的测试运行器以及通过正常Python错误堆栈管道错误的任何建议?与往常一样,如果您认为有更好的方法来解决这个问题,请告诉我。
编辑:
以下是我最终用来解决此问题的方法。首先,我在我的测试类中添加了一个“get_test_names()”方法:
class my_test(unittest.TestCase):
etc....
@staticmethod
def get_test_names():
"""Return the names of all the test methods for this class."""
test_names = [ member[0] for memeber in inspect.getmembers(my_test)
if 'test_' in member[0] ]
然后我用以下内容将我的电话换成了unittest.main()
:
# Unittest catches all errors raised by the test cases, and returns them as
# formatted strings inside a TestResult object. In order for the test
# harness to catch these errors they need to be re-raised, and so I am defining
# this CompareError class to do that.
# For each code error, a CompareError will be raised, with the original error
# stack as the argument. For test failures (i.e. assertion errors) an
# AssertionError is raised.
class CompareError(Exception):
def __init__(self,err):
self.err = err
def __str__(self):
return repr(self.err)
# Collect all tests into a TestSuite()
all_tests = ut.TestSuite()
for test in my_test.get_test_names():
all_tests.addTest(my_test(test))
# Define a TestResult object and run tests
results = ut.TestResult()
all_tests.run(results)
# Re-raise any script errors
for error in results.errors:
raise CompareError(error[1])
# Re-raise any test failures
for failure in results.failures:
raise AssertionError(failure[1])
答案 0 :(得分:3)
我想出了这个。如果您能够更改命令行,则可以删除内部io重定向。
import sys, inspect, traceback
# redirect stdout,
# can be replaced by testharness.py > /dev/null at console
class devnull():
def write(self, data):
pass
f = devnull()
orig_stdout = sys.stdout
sys.stdout = f
class TestCase():
def test_1(self):
print 'test_1'
def test_2(self):
raise AssertionError, 'test_2'
def test_3(self):
print 'test_3'
if __name__ == "__main__":
testcase = TestCase()
testnames = [ t[0] for t in inspect.getmembers(TestCase)
if t[0].startswith('test_') ]
for testname in testnames:
try:
getattr(testcase, testname)()
except AssertionError, e:
print >> sys.stderr, traceback.format_exc()
# restore
sys.stdout = orig_stdout