簡體   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