簡體   English   中英

如何在變量中捕獲單元測試的標准輸出/標准錯誤?

[英]How to capture the stdout/stderr of a unittest in a variable?

如何在變量中捕獲單元測試的標准輸出/標准錯誤? 我需要捕獲以下單元測試的整個輸出輸出並將其發送到 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

任何的想法? 如果需要更多信息,請告訴我。

如果您手動實例化測試運行程序(例如unittest.TextTestRunner ),您可以指定它寫入的(文件)流。 默認情況下這是sys.stderr ,但您可以使用 StringIO 代替。 這將捕獲單元測試本身的輸出。 您自己的打印語句的輸出不會被捕獲,但您可以使用redirect_stdout上下文管理器,使用相同的 StringIO 對象。

請注意,我建議避免使用打印語句,因為它們會干擾 unittest 框架的輸出(您的測試輸出將破壞 unittest 框架的輸出行)並且重定向 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 對象中。

根據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())

老實說,最簡單的方法可能是在操作系統級別重定向您的輸出——從命令行運行測試,然后將其 > 放到一個文件中。

如果您使用構建系統來執行這些,那么構建系統應該為您捕獲輸出,您可以從它的構建工件中提取輸出。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM