2017-02-21 160 views
0

我想捕捉和它做到这一点的函数分析输出sys.stdout的(错了,在):如何嘲笑为subprocess.call

subprocess.call(参数,标准输入= sys.stdin,标准输出= sys.stdout的,标准错误= sys.stderr)

当我下运行py.test没有任何嘲笑这个代码,我得到错误:ValueError: redirected Stdin is pseudofile, has no fileno()

当我与模拟补丁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()

任何方式来传递某种模拟对象为标准输入/输出的子进程?

我想是这样的:

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

当在py.test运行哪些应该工作。

谢谢。

+0

你为什么不嘲笑'subprocess.call'?你不测试'subprocess'是否工作,只有* *使用*'subprocess'的代码有效。 –

+0

有人可能会争辩说,测试外部命令是否正常工作不是你的工作;你想模拟'subprocess_call'本身。 – chepner

+0

这个测试是集成测试的一部分,我只模拟stdout/err来检查命令结果(因为否则它们会直接进入用户终端)。我需要实际的外部程序输出(来自'args'),看看我的程序和外部程序都做了他们应该做的事情。 –

回答

0

经过一番斗争,我找到了一种方法来修补和拦截标准输出为subprocess.call

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

与此同时,我真的很想避免创建任何文件,因为它确实会使测试的设置/拆卸复杂化。我决定用os.pipe调用创建防卫和安全使用这些标准输出捕获从subprocess.call

这里简化我的测试版本:

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