如何为subprocess.call

时间:2017-02-21 18:45:09

标签: python mocking subprocess pytest

我想捕获和分析执行此操作的函数的输出:

subprocess.call(args,stdin = sys.stdin,stdout = sys.stdout,stderr = sys.stderr)

当我在py.test下运行此代码而没有任何模拟时,我收到错误:ValueError: redirected Stdin is pseudofile, has no fileno()

当我用mock修补sys.stdin(和其他人)时,我得到同样的错误。

当我使用mock.mock_open()修补sys.stdin时,我收到错误:AttributeError: Mock object has no attribute 'write'

当我使用mock.mock_open()('name', 'r')修补sys.stdin时,我收到了初始错误:ValueError: redirected Stdin is pseudofile, has no fileno()

有没有办法将某种模拟对象作为stdin / out传递给子进程?

我想要这样的事情:

mocked = (put something here)
subprocess_call('ls', stdin=mocked, stdout=mocked, stderr=mocked)

在py.test下运行时应该有效。

感谢。

1 个答案:

答案 0 :(得分:1)

经过一番努力,我找到了一种方法来修补和拦截subprocess.call的标准输出。

我的主要问题是call函数的非模拟版本需要来自操作系统的实际FD。没有模拟能够为我提供这样的东西。

同时我真的想避免创建任何文件,因为它会使测试的设置/拆卸变得复杂。我决定使用os.pipe调用来创建FD并将其用于subprocess.call

的stdout捕获

这是我测试的简化版本:

def test_exec_results(ssh):
    rfd, wfd = os.pipe()
    w = os.fdopen(wfd, 'w', 0)
    with mock.patch.multiple(app.sys, stdout=w, stderr=w, stdin=None):
        app.myfunction('test message')
    output = os.read(rfd, 1000)
    assert 'test message ' in output
    assert 'some_other_things' in output