2014-01-13 139 views
3

我目前正在測試我的Python代碼,並有一個關於raw_input的問題。這是我的函數:Python測試原始輸入,原始輸入if語句

def answer(): 
    ans = raw_input('enter yes or no') 
    if ans == 'yes': 
     print 'you entered yes' 
     return 'yes' 
    if ans == 'no': 
     some_value = raw_input('enter some value: ') 
     print 'you entered no' 
     return some_value 

我測試的第一if語句是這樣的:

with mock.patch('__builtin__.raw_input', return_value= 'yes'): 
    assert answer() == 'yes' 

但我怎麼查不聲明?我該如何在模擬中進行模擬?

回答

4

使用side_effect

with mock.patch('__builtin__.raw_input', side_effect=['yes']): 
    assert answer() == 'yes' 
with mock.patch('__builtin__.raw_input', side_effect=['no', 'maybe']): 
    assert answer() == 'maybe' 

根據mock documentation

如果side_effect是一個迭代,然後每次調用模擬將返回從可迭代的下一個值。 side_effect也可以是任何可迭代的對象。重複調用模擬將從迭代器返回值(直到迭代耗盡,一個StopIteration升高):

>>> 
>>> m = MagicMock(side_effect=[1, 2, 3]) 
>>> m() 
1 
>>> m() 
2 
>>> m() 
3 
>>> m() 
Traceback (most recent call last): 
    ... 
StopIteration 
0

如果你只是模擬raw_input返回'no',它將返回兩次'no',意義可以斷言,函數返回'no'

with mock.patch('__builtin__.raw_input', return_value='yes'): 
    assert answer() == 'yes' 
with mock.patch('__builtin__.raw_input', return_value='no'): 
    assert answer() == 'no' 

如果你想測試會發生什麼如果說,第一輸入'no',第二個是'maybe',你要嘲笑我t函數在第一次被調用時和第二次被調用時返回不同的東西,然後你可以聲明它返回'maybe'。事情是這樣的(未測試,因爲我沒有在這裏做安裝mock ...但它應該給你的想法):

def fake_raw_input(once=[False]): 
    if not once[0]: 
     once[0] = True 
     return 'no' 
    return 'maybe' 

with mock.patch('__builtin__.raw_input', return_value='yes'): 
    assert answer() == 'yes' 
with mock.patch('__builtin__.raw_input', new_callable=fake_raw_input): 
    assert answer() == 'maybe' 
2

使用副作用應該做的伎倆,我發現下面很清晰,避免多次與-block:

def my_side_effect(*args): # each argument will be the return_value of one call 
    for el in args: 
     yield el # we use a generator to return different value each time 

with mock.patch('__builtin__.raw_input') as mocked: # here the mocked object is accessible in the block 
    mocked.side_effect = my_side_effect('yes') # here one call that return 'yes' 
    assert answer() == 'yes' 
    mocked.side_effect = my_side_effect('no', 'maybe') # two calls, the first return 'no', the second 'maybe' 
    assert answer() == 'maybe' 
+0

我沒有意識到'side_effect'可以帶上這樣的發電機。發電機總是最簡單的方式來捆綁簡單的狀態。 +1,只是因爲我不能+10。 – abarnert