2017-02-21 94 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