次のような条件が発生した場合のテストの作成方法:
誰かが上記のシナリオにアプローチする方法を教えてくれたら素晴らしいと思います。私が読むことができるいくつかのドキュメント/記事/ブログの投稿を私に指摘していただければ、それでも素晴らしいでしょう。
説明した3つの状況はすべて、設計で疎結合を使用していることを確認するために、特に邪魔にならないようにする必要がある場合です。
本当に Pythonのraw_input
メソッドをユニットテストする必要がありますか? open
メソッド? os.environ.get
?番号。
その入力を取得する他の方法に置き換えることができるように、デザインを設定する必要があります。次に、単体テスト中に、実際にはraw_input
またはopen
を呼び出さない種類のスタブをスローします。
たとえば、通常のコードは次のようになります。
import os
def say_hello(input_func):
name = input_func()
return "Hello " + name
def Prompt_for_name():
return raw_input("What is your name? ")
print say_hello(Prompt_for_name)
# Normally would pass in methods, but lambdas can be used for brevity
print say_hello(lambda: open("a.txt").readline())
print say_hello(lambda: os.environ.get("USER"))
セッションは次のようになります。
お名前は何ですか?誰か こんにちは誰か こんにちは[いくつかのテキスト] こんにちはマーク
次に、テストは次のようになります。
def test_say_hello():
output = say_hello(lambda: "test")
assert(output == "Hello test")
言語のIO機能をテストする必要はないことに注意してください(言語を設計しているのがあなたである場合を除きます。これはまったく別の状況です)。
Raw_input(または他の特定の入力ソース)の使用に縛られている場合、私は モックライブラリ の大きな支持者です。 Mark Rushakoffが彼の例で使用したコードを考えると:
def say_hello():
name = raw_input("What is your name? ")
return "Hello " + name
テストコードでモックを使用できます。
import mock
def test_say_hello():
with mock.patch('__builtin__.raw_input', return_value='dbw'):
assert say_hello() == 'Hello dbw'
with mock.patch('__builtin__.raw_input', side_effect=['dbw', 'uki']):
assert say_hello() == 'Hello dbw'
assert say_hello() == 'Hello uki'
これらのアサーションは合格します。 side_effectは、リストの要素を順番に返すことに注意してください。それはもっとたくさんのことができます!ドキュメントをチェックすることをお勧めします。
外部プロセスを使用せずに逃げることができる場合は、そうしてください。
ただし、これが複雑で、実際にプロセスを使用したい場合があります。たとえば、C実行可能ファイルのコマンドラインインターフェイスをテストしたい場合などです。
ユーザー入力
次のように_subprocess.Popen
_を使用します。
_process = subprocess.Popen(
command,
Shell = False,
stdin = subprocess.PIPE,
stdout = subprocess.PIPE,
stderr = subprocess.PIPE,
universal_newlines = True
)
stdout, stderr = process.communicate("the user input\nline 2")
exit_status = process.wait()
_
_raw_input
_やsys.stdin.read()
などのメソッドを使用して、ユーザーから入力を取得することと、パイプから入力を取得することに違いはありません。
ファイル
一時ディレクトリを作成し、そこから読み取りたいファイルをテストsetUp
メソッドで作成します。
_tdir = tempfile.mkdtemp(
prefix = 'filetest_',
)
fpath = os.path.join(tdir,'filename')
fp = open(fpath, 'w')
fp.write("contents")
fp.close()
_
テストでファイルの読み取りを行います。
その後、一時ディレクトリを削除します。
_shutil.rmtree(tdir)
_
ファイルからの読み取りは非常に複雑であり、ほとんどのプログラムはファイルまたはSTDINから読み取ることができます(例:fileinput
)。したがって、テストしたいのが特定のコンテンツが入力されたときに何が起こるかであり、プログラムがSTDINを受け入れる場合は、Popen
を使用してプログラムをテストします。
環境変数
os.environ["THE_VAR"] = "the_val"
_で環境変数を設定しますdel os.environ["THE_VAR"]
_で設定を解除しますos.environ = {'a':'b'}
_が機能しないsubprocess.Popen
_を呼び出します。環境は呼び出しプロセスから継承されます。テンプレートコード
my github に、STDOUT
、STDERR
、およびSTDIN
で指定された終了ステータス、コマンドライン引数、および環境をテストするモジュールがあります。また、「tests」ディレクトリでそのモジュールのテストを確認してください。これにはもっと良いモジュールがあるはずなので、学習目的のためだけに私のものを持っていってください。
pytest を使用する:
import os
def test_user_input(monkeypatch):
inputs = [10, 'y']
input_generator = (i for i in inputs)
monkeypatch.setattr('__builtin__.raw_input', lambda Prompt: next(input_generator))
assert raw_input('how many?') == 10
assert raw_input('you sure?') == 'y'
def test_file_input(tmpdir):
fixture = tmpdir.join('fixture.txt')
fixture.write(os.linesep.join(['1', '2', '3']))
fixture_path = str(fixture.realpath())
with open(fixture_path) as f:
assert f.readline() == '1' + os.linesep
def test_environment_input(monkeypatch):
monkeypatch.setenv('STAGING', 1)
assert os.environ['STAGING'] == '1'