繁体   English   中英

如何在unittest中捕获python子进程stdout

[英]How to capture python subprocess stdout in unittest

我正在尝试编写一个单元测试,该单元测试执行写入stdout的功能,捕获该输出并检查结果。 有问题的函数是一个黑匣子:我们无法更改其写入输出的方式。 出于本示例的目的,我已经对其进行了相当多的简化,但是实质上该函数使用subprocess.call()生成其输出。

无论我尝试什么,都无法捕获输出。 它始终被写入屏幕,并且测试失败,因为它没有捕获任何内容。 我尝试了print()和os.system()。 使用print()可以捕获标准输出,但是不能使用os.system()捕获。

它也不特定于单元测试。 我没有用相同的结果编写测试示例。

与此类似的问题已经问了很多,答案似乎都归结为使用subprocess.Popen()和communication(),但这将需要更改黑框。 我敢肯定我还没有找到答案,但是我很困惑。

我们正在使用Python-2.7。

无论如何,我的示例代码是这样的:

#!/usr/bin/env python
from __future__ import print_function
import sys
sys.dont_write_bytecode = True

import os
import unittest
import subprocess
from contextlib import contextmanager
from cStringIO import StringIO

# from somwhere import my_function
def my_function(arg):
    #print('my_function:', arg)
    subprocess.call(['/bin/echo', 'my_function: ', arg], shell=False)
    #os.system('echo my_function: ' + arg)

@contextmanager
def redirect_cm(new_stdout):
    old_stdout =  sys.stdout
    sys.stdout =  new_stdout
    try:
        yield
    finally:
        sys.stdout = old_stdout

class Test_something(unittest.TestCase):
   def test(self):
        fptr = StringIO()
        with redirect_cm(fptr):
            my_function("some_value")

        self.assertEqual("my_function: some_value\n", fptr.getvalue())

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

上面的代码有两个问题

  1. StringIO fptr不被当前和生成的进程共享,即使生成的进程已将结果写入StringIO对象,我们也无法在当前进程中获取结果

  2. 更改sys.stdout不会影响 os模块中os.popen()os.system()exec*()系列函数执行的标准I / O流程

一个简单的解决方案是

  1. 使用os.pipe在两个进程之间共享结果

  2. 使用os.dup2而不是更改sys.stdout

演示示例如下所示

import sys
import os
import subprocess
from contextlib import contextmanager


@contextmanager
def redirect_stdout(new_out):
    old_stdout = os.dup(1)
    try:
        os.dup2(new_out, sys.stdout.fileno())
        yield
    finally:
        os.dup2(old_stdout, 1)


def test():
    reader, writer = os.pipe()

    with redirect_stdout(writer):
        subprocess.call(['/bin/echo', 'something happened what'], shell=False)

    print os.read(reader, 1024)


test()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM