5

printand関数を直接使用するいくつかの(python 3)コードをテストしたいと思いinputます。私が理解しているように、これを行う最も簡単な方法は、依存性注入によるものです。入力ストリームと出力ストリームを引数として受け取るようにコードを変更し、デフォルトでテスト中にモックオブジェクトを使用sys.stdinして渡します。呼び出しsys.stdoutをどうするかは明らかです:print

print(text)
#replaced with...
print(text, file=output_stream)

ただし、input入力ストリームと出力ストリームの引数はありません。次のコードはその動作を正しく再現していますか?

text = input(prompt)
#replaced with...
print(prompt, file=output_stream, end='')
text = input_stream.readline()[:-1]

私はの実装を調べましたが、メソッドを呼び出すのではなく、呼び出して調べ、メソッドを呼び出すのではなくinput、非常に多くの魔法を実行します。これらのモックをどこから始めればよいのかわかりません。sys.stdin.filenosys.stdin.encodingsys.stdin.errorsread*

4

2 に答える 2

7

input()あなたが言及した魔法は、変更されていない場合にのみ実行されますstdinstdoutそれは、その場合にのみ、readlineライブラリなどを使用できるためです。それらを他のもの(実ファイルかどうか)に置き換えると、次のコードになります。

/* Fallback if we're not interactive */
if (promptarg != NULL) {
    if (PyFile_WriteObject(promptarg, fout, Py_PRINT_RAW) != 0)
         return NULL;
}
tmp = _PyObject_CallMethodId(fout, &PyId_flush, "");
if (tmp == NULL)
    PyErr_Clear();
else
    Py_DECREF(tmp);
return PyFile_GetLine(fin, -1);

ここPyFile_GetLine でメソッドを呼び出しますreadline。したがって、モックsys.std*は機能します。

テストしているコードが例外で失敗した場合でも出力が復元されるようにtry: finally:、コンテキストプロセッサまたはモジュールを使用してこれを行うことをお勧めします。mock

from unittest.mock import patch
from io import StringIO

with patch("sys.stdin", StringIO("FOO")), patch("sys.stdout", new_callable=StringIO) as mocked_out:
    x = input()
    print("Read:", x)

assert mocked_out.getvalue() == "Read: FOO\n"
于 2012-11-05T20:11:49.883 に答える
6

ファイルのようなオブジェクトをsys.stdinPython のinput関数に割り当てると、標準入力の代わりにそれが使用されます。ただしsys.stdin、使い終わったら、忘れずに標準入力に再割り当てしてください。同じトリックが にも適用されsys.stdoutます。次のようなことができます。

original_stdin = sys.stdin
sys.stdin = open('inputfile.txt', 'r')

original_stdout = sys.stdout
sys.stdout = open('outputfile.txt', 'w')

response = input('say hi: ')
print(response)

sys.stdin = original_stdin
sys.stdout = original_stdout

この2行

response = input('say hi: ')
print(response)

標準入力と標準出力の代わりに、指定されたファイル (inputfile.txtと) を使用します。outputfile.txt

更新: 物理ファイルを扱いたくない場合は、ioモジュールを見てください。io.StringIOインメモリ テキスト ストリーム操作を実行できるクラスを提供します。

original_stdin = sys.stdin
sys.stdin = io.StringIO('input string')

original_stdout = sys.stdout
sys.stdout = io.StringIO()

response = input('say hi: ')
print(response)

output = sys.stdout.getvalue()

sys.stdin = original_stdin
sys.stdout = original_stdout

print(output)
于 2012-11-05T19:27:27.387 に答える