[英]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()
上面的代碼有兩個問題
StringIO fptr
不被當前和生成的進程共享,即使生成的進程已將結果寫入StringIO
對象,我們也無法在當前進程中獲取結果
更改sys.stdout
不會影響 os模塊中os.popen()
, os.system()
或exec*()
系列函數執行的標准I / O流程流
一個簡單的解決方案是
使用os.pipe
在兩個進程之間共享結果
使用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.