我有一个python3.7脚本,该脚本将YAML文件作为输入并根据其中的说明进行处理。我用于单元测试的YAML文件如下所示:
...
tasks:
- echo '1'
- echo '2'
- echo '3'
- echo '4'
- echo '5'
该脚本循环执行任务,然后使用os.system()
调用运行每个任务。
手动测试表明,输出符合预期:
1
2
3
4
5
但是我无法使其在单元测试中起作用。这是我尝试捕获输出的方法:
from application import application
from io import StringIO
import unittest
from unittest.mock import patch
class TestApplication(unittest.TestCase):
def test_application_tasks(self):
expected = ['1','2','3','4','5']
with patch('sys.stdout', new=StringIO()) as fakeOutput:
application.parse_event('some event') # print() is called here within parse_event()
self.assertEqual(fakeOutput.getvalue().strip().split(), expected)
运行python3 -m unittest discover -s tests
时,我得到的只是AssertionError: Lists differ: [] != ['1', '2', '3', '4', '5']
。
我也尝试使用with patch('sys.stdout', new_callable=StringIO) as fakeOutput:
,但无济于事。
我尝试的另一件事是self.assertEqual(fakeOutput.getvalue(), '1\n2\n3\n4\n5')
,这是单元测试输出的内容:
AssertionError: '' != '1\n2\n3\n4\n5'
+ 1
+ 2
+ 3
+ 4
+ 5
很明显,该脚本可以工作并输出正确的结果,但是fakeOutput
不能捕获它。
使用patch
作为修饰符也不起作用:
from application import application
from io import StringIO
import unittest
from unittest.mock import patch
class TestApplication(unittest.TestCase):
@patch('sys.stdout', new_callable=StringIO)
def test_application_tasks(self):
expected = ['1','2','3','4','5']
application.parse_event('some event') # print() is called here within parse_event()
self.assertEqual(fakeOutput.getvalue().strip().split(), expected)
将输出绝对相同的错误:AssertionError: Lists differ: [] != ['1', '2', '3', '4', '5']
答案 0 :(得分:1)
os.system
运行一个新进程。如果您对sys.stdout
进行猴子补丁,这会影响当前进程,但不会对任何新进程造成影响。
考虑:
import sys
from os import system
from io import BytesIO
capture = sys.stdout = BytesIO()
system("echo Hello")
sys.stdout = sys.__stdout__
print(capture.getvalue())
没有捕获任何内容,因为只有子进程已写入其标准输出。没有任何东西可以写到您的Python进程的标准输出中。
通常,避免使用os.system
。而是使用subprocess
模块,该模块可让您捕获正在运行的进程的输出。
答案 1 :(得分:1)
您的解决方案很好,只需使用 getvalue
代替,如下所示:
with patch("sys.stdout", new_callable=StringIO) as f:
print("Foo")
r = f.getvalue()
print("r: {r!r} ;".format(r=r))
<块引用>
r: "Foo" ;
答案 2 :(得分:0)
谢谢你,让·保罗·卡尔德隆(Jean-Paul Calderone)。我意识到,os.system()
创建了一个完全不同的过程,因此,只有在发布问题后才需要以不同的方式解决问题:)
要真正能够测试我的代码,我不得不使用subprocess
而不是os.system()
对其进行重写。最后,我选择了subprocess_run_result = subprocess.run(task, shell=True, stdout=subprocess.PIPE)
,然后使用subprocess_run_result.stdout.strip().decode("utf-8")
得到了结果。
在测试中,我只创建一个类的实例并调用一个方法,该方法在子进程中运行任务。
如果有人想看看,我整个重构的代码和测试都是here in this commit。