运行 Python unittest,如果成功则不打印任何内容,如果失败则只打印 AssertionError() [英] Run Python unittest so that nothing is printed if successful, only AssertionError() if fails

查看:66
本文介绍了运行 Python unittest,如果成功则不打印任何内容,如果失败则只打印 AssertionError()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个标准单元测试格式的测试模块

I have a test module in the standard unittest format

class my_test(unittest.TestCase):

    def test_1(self):
        [tests]

    def test_2(self):
        [tests]
  etc....

我的公司有一个专有的测试工具,可以将我的模块作为命令行脚本来执行,它会捕获我的模块引发的任何错误,但如果成功则要求我的模块静音.

My company has a proprietary test harness that will execute my module as a command line script, and which will catch any errors raised by my module, but requires that my module be mute if successful.

所以,我试图找到一种方法来裸机运行我的测试模块,这样如果我的所有测试都通过了,那么屏幕上不会打印任何内容,如果测试失败并出现 AssertionError,则该错误会通过标准传递Python 错误堆栈(就像普通 Python 脚本中的任何其他错误一样.)

So, I am trying to find a way to run my test module naked, so that if all my tests pass then nothing is printed to the screen, and if a test fails with an AssertionError, that error gets piped through the standard Python error stack (just like any other error would in a normal Python script.)

docs 提倡使用 unittest.main() 函数来运行所有测试在给定的模块中,如

The docs advocate using the unittest.main() function to run all the tests in a given module like

if __name__ == "__main__":
    unittest.main()

问题在于,这将测试结果包装在unittest的harness中,这样即使所有测试都成功了,它仍然会在屏幕上打印一些绒毛,如果出现错误,它不会像通常的python错误那样简单地转储,而且还穿着马具.

The problem is that this wraps the test results in unittest's harness, so that even if all tests are successful, it still prints some fluff to the screen, and if there is an error, it's not simply dumped as a usual python error, but also dressed in the harness.

我尝试使用

with open('.LOG','a') as logf:
    suite = unittest.TestLoader().loadTestsFromTestCase(my_test)
    unittest.TextTestRunner(stream = logf).run(suite)

这里的问题是一切都通过管道传输到日志文件(包括所有错误通知).因此,当我的公司工具运行该模块时,它成功完成,因为据它所知,没有出现错误(因为它们都通过管道传输到日志文件).

The problem here is that EVERYTHING gets piped to the log file (including all notice of errors). So when my companies harness runs the module, it complete's successfully because, as far as it can tell, no errors were raised (because they were all piped to the log file).

关于如何构建一个测试运行器来抑制所有错误并通过正常的 Python 错误堆栈传输错误有什么建议吗?与往常一样,如果您认为有更好的方法来解决这个问题,请告诉我.

Any suggestions on how I can construct a test runner that suppresses all the fluff, and pipes errors through the normal Python error stack? As always, if you think there is a better way to approach this problem, please let me know.

这是我最终用来解决此问题的方法.首先,我在我的测试类中添加了一个get_test_names()"方法:

Here is what I ended up using to resolve this. First, I added a "get_test_names()" method to my test class:

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() 的调用替换为以下内容:

Then I replaced my call to unittest.main() with the following:

# 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])

推荐答案

我想出了这个.如果您能够更改命令行,则可能会删除内部 io 重定向.

I came up with this. If you are able to change the command line you might remove the internal io redirection.

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

这篇关于运行 Python unittest,如果成功则不打印任何内容,如果失败则只打印 AssertionError()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆