私はpythons mock.patchを使用していますが、各呼び出しの戻り値を変更したいと思います。ここで注意点があります。パッチを適用する関数には入力がないため、入力に基づいて戻り値を変更することはできません。
参照用のコードを次に示します。
def get_boolean_response():
response = io.Prompt('y/n').lower()
while response not in ('y', 'n', 'yes', 'no'):
io.echo('Not a valid input. Try again'])
response = io.Prompt('y/n').lower()
return response in ('y', 'yes')
私のテストコード:
@mock.patch('io')
def test_get_boolean_response(self, mock_io):
#setup
mock_io.Prompt.return_value = ['x','y']
result = operations.get_boolean_response()
#test
self.assertTrue(result)
self.assertEqual(mock_io.Prompt.call_count, 2)
io.Prompt
は、プラットフォームに依存しない(python 2および3)バージョンの「入力」です。したがって、最終的にはユーザーの入力をモックアウトしようとしています。戻り値にリストを使用しようとしましたが、うまくいきません。
戻り値が無効なものである場合、ここで無限ループが発生することがわかります。したがって、テストが実際に終了するように、最終的に戻り値を変更する方法が必要です。
(この質問に答える別の可能な方法は、ユニットテストでユーザー入力を模倣する方法を説明することです)
この質問 の重複ではありません。主に、入力を変更する能力がないためです。
この質問 に関する回答のコメントの1つは同じ行に沿っていますが、回答/コメントは提供されていません。
iterable をside_effect
に割り当てると、モックは呼び出されるたびにシーケンス内の次の値を返します。
>>> from unittest.mock import Mock
>>> m = Mock()
>>> m.side_effect = ['foo', 'bar', 'baz']
>>> m()
'foo'
>>> m()
'bar'
>>> m()
'baz'
Mock()
documentation の引用:
side_effectが反復可能な場合、モックの各呼び出しは反復可能な要素から次の値を返します。
余談ですが、テストresponse is not 'y' or 'n' or 'yes' or 'no'
はnot動作します。式(response is not 'y')
が真であるか、'y'
が真である(常に、空でない文字列が常に真である)かなどを尋ねています。or
演算子の両側のさまざまな式は独立。 1つの変数を複数の値に対してテストするにはどうすればよいですか? を参照してください。
alsoは、文字列に対してテストするためにis
を使用しないでください。 CPythonインタープリターmay文字列オブジェクトの再利用 特定の状況下 ですが、これは期待すべき動作ではありません。
そのため、次を使用します。
response not in ('y', 'n', 'yes', 'no')
代わりに;これはequalityテスト(==
)を使用して、response
が同じ内容(値)の文字列を参照しているかどうかを判断します。
同じことがresponse == 'y' or 'yes'
にも当てはまります。代わりにresponse in ('y', 'yes')
を使用してください。