如何在变量中捕获UNITSEST的Stdout/Stderr



如何在变量中捕获UNITSEST的Stdout/stderr?我需要捕获以下单元测试的整个输出,并将其发送到SQS。我已经尝试过:

import unittest, io
from contextlib import redirect_stdout, redirect_stderr

class LogProcessorTests(unittest.TestCase):
    def setUp(self):
        self.var = 'this value'
    def test_var_value(self):
        with io.StringIO() as buf, redirect_stderr(buf):
            print('Running LogProcessor tests...')
            print('Inside test_var_value')
            self.assertEqual(self.var, 'that value')
            print('-----------------------')
            print(buf.getvalue())

但是,它不起作用,以下输出仅在stdout/stderr上出现。

Testing started at 20:32 ...
/Users/myuser/Documents/virtualenvs/app-venv3/bin/python3 "/Applications/PyCharm CE.app/Contents/helpers/pycharm/_jb_unittest_runner.py" --path /Users/myuser/Documents/projects/application/LogProcessor/tests/test_processor_tests.py
Launching unittests with arguments python -m unittest /Users/myuser/Documents/projects/application/LogProcessor/tests/test_processor_tests.py in /Users/myuser/Documents/projects/application/LogProcessor/tests
Running LogProcessor tests...
Inside test_var_value
that value != this value
Expected :this value
Actual   :that value
<Click to see difference>
Traceback (most recent call last):
  File "/Applications/PyCharm CE.app/Contents/helpers/pycharm/teamcity/diff_tools.py", line 32, in _patched_equals
    old(self, first, second, msg)
  File "/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/unittest/case.py", line 839, in assertEqual
    assertion_func(first, second, msg=msg)
  File "/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/unittest/case.py", line 1220, in assertMultiLineEqual
    self.fail(self._formatMessage(msg, standardMsg))
  File "/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/unittest/case.py", line 680, in fail
    raise self.failureException(msg)
AssertionError: 'this value' != 'that value'
- this value
?   ^^
+ that value
?   ^^
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/unittest/case.py", line 59, in testPartExecutor
    yield
  File "/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/unittest/case.py", line 615, in run
    testMethod()
  File "/Users/myuser/Documents/projects/application/LogProcessor/tests/test_processor_tests.py", line 15, in test_var_value
    self.assertEqual(self.var, 'that value')

Ran 1 test in 0.004s
FAILED (failures=1)
Process finished with exit code 1
Assertion failed
Assertion failed

有什么想法吗?请让我知道是否需要更多信息。

基于contextLib.redirect_stdout文档,这是您重定向 stderrstdout

的方式
import io
import contextlib
f = io.StringIO()
with contextlib.redirect_stderr(f):
    parser = target.parse_args([])
self.assertTrue("error: one of the arguments -p/--propagate -cu/--cleanup is required" in f.getvalue())

您也可以将其与其他上下文管理器(如assertRaises(相结合:

f = io.StringIO()
with self.assertRaises(SystemExit) as cm, contextlib.redirect_stderr(f):
    parser = target.parse_args([])
self.assertEqual(cm.exception.code, 2)
self.assertTrue("error: one of the arguments -p/--propagate -cu/--cleanup is required" in f.getvalue())

如果您手动实例化测试跑者(例如unittest.TextTestRunner(,则可以指定它写入的(文件(流。默认情况下,这是sys.stderr,但是您可以使用Stringio。这将捕获UNITSEST本身的输出。不会捕获自己的打印件的输出,但是您可以使用同一Stringio对象使用redirect_stdout上下文管理器。

请注意,我建议避免使用打印仪,因为它们会干扰Unittest Framework的输出(您的测试输出将破坏Unittest Framework的输出线(,并且将其重定向到Stdout/stderr流。更好的解决方案是使用logging模块。然后,您可以添加一个记录处理程序,将所有日志消息写入Stringio以进行进一步处理(在您的情况下:发送到SQS(。

下面是使用打印件基于您的代码的示例代码。

#!/usr/bin/env python3
import contextlib
import io
import unittest

class LogProcessorTests(unittest.TestCase):
    def setUp(self):
        self.var = 'this value'
    def test_var_value(self):
        print('Running LogProcessor tests...')
        print('Inside test_var_value')
        self.assertEqual(self.var, 'that value')
        print('-----------------------')

if __name__ == '__main__':
    # find all tests in this module
    import __main__
    suite = unittest.TestLoader().loadTestsFromModule(__main__)
    with io.StringIO() as buf:
        # run the tests
        with contextlib.redirect_stdout(buf):
            unittest.TextTestRunner(stream=buf).run(suite)
        # process (in this case: print) the results
        print('*** CAPTURED TEXT***:n%s' % buf.getvalue())

此打印:

*** CAPTURED TEXT***:
Running LogProcessor tests...
Inside test_var_value
F
======================================================================
FAIL: test_var_value (__main__.LogProcessorTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test.py", line 16, in test_var_value
    self.assertEqual(self.var, 'that value')
AssertionError: 'this value' != 'that value'
- this value
?   ^^
+ that value
?   ^^

----------------------------------------------------------------------
Ran 1 test in 0.000s
FAILED (failures=1)

这证实了在Stringio对象中捕获的所有输出(来自Unittest Framework和TestCase本身(。

老实说,最简单的方法可能是在OS级别上重定向输出 - 从命令行中运行测试并> IT到文件。

如果您使用构建系统执行这些系统,则构建系统应为您捕获输出,并且可以从其构建工件中提取输出。

最新更新