如何使用在后台运行的fixture捕获python中的stdout和stderr

时间:2017-05-04 21:15:18

标签: python logging fixture

我想为一组测试编写自定义记录器,而不对测试进行任何重大更改。我想使用类似于夹具的东西,我可以将其传递给测试方法,夹具在整个测试过程中在后台运行,捕获stdout和stderr并将其更改为自定义消息。怎么办呢?

def test_1():
   blah
   blah
   print('Some msg')
   blah
   assert something, assert_msg

Output:
Some msg (if assert fails, then assertion error too)

我想要的是

@fixture
def logger():
    capture stdout, stderr
    custom_msg = cust_msg(stdout, stderr)
    print(custom_msg)


def test_1(logger):
   blah
   blah
   print('Some msg')
   blah
   assert something, assert_msg

Output:
Custom msg (if assert fails, then custom assertion error too)

1 个答案:

答案 0 :(得分:0)

您无法从模块中捕获标准输出,无需重新定义sys.stdoutprint。重新定义打印更容易,因为它已经是一个功能。要抓住失败的assert,只需抓住AssertionError s。

import functools
import sys

def fixture(f):
    old_print = print
    @functools.wraps(f)
    def wrapped(*args, **kwargs):
        global print
        def print(*value, sep=' ', end='\n', file=sys.stdout, flush=False):
            msg = sep.join(map(str, value)) + end

            # Manipulate msg here

            file.write(manipulated)
            if flush:
                file.flush()
        try:
            return f(*args, **kwargs)
        except AssertionError as e:

            # Custom message on failed assertion
            msg = e.args[0] if len(e.args) == 1 else None
            old_print(manipulated)

        finally:
            print = old_print
    return wrapped

但是,assert并不能提供更多有用的信息。我会使用一个实际的测试库,比如unittest

另一种方法是将其作为子流程运行。