今日は、pytestのパラメータ化について書いておく。
要約
方法 | メリット | デメリット |
---|---|---|
@pytest.mark.parametrizeを利用する | 直感的にかける | 前処理、後処理が出来ない |
@pytest.fixtureを利用する | 前処理、後処理ができる | テストが冗長になる。 |
pytest_generate_tests(フック関数)を利用する。 | 複雑なデータセットで検証できる | 直感的でない |
個人的には、
前処理、後処理が不必要な場合:@pytest.mark.parametrize
前処理、後処理が必要な場合:@pytest.fixture
で使い分けている。
※ まだ、pytestを書き始めたばかりなので、pytest_generate_testsの強みが・・・・
対象ソースコード
def add(a: int, b: int):
return a + b
@pytest.mark.parametrize
@pytest.mark.parametrize("x,y,result", [(1, 2, 3), (-1, 2, 1), (-1, -4, -5), (0, 0, 0)])
def test_add(x, y, result):
assert result == add(x, y)
「x,y,result」がそれぞれの引数に入るので直感的でわかりやすい。
@pytest.fixture
@pytest.fixture(params=[(1, 2, 3), (-1, 2, 1), (-1, -4, -5), (0, 0, 0)])
def start_state(request):
print("前処理")
yield request.param
print("後処理")
def test_add_pytest_fixture(start_state):
x, y, result = start_state
assert result == add(x, y)
- start_stateの中で、前処理、及び 後処理が記載できる。(yieldを使うことで、各行で呼び出し元に行く)
- request.paramの中に@pytest.fixtureのparamが入っている。
- テストの引数で@pytest.fixtureがついているメソッド名を記載する。(pytestが自動で読み込んでくれる)
やはり、「前処理」と「後処理」がかけるのが強みであろう。
一方で、メソッドを追加しないといけないので多少冗長である。
また、引数のstart_stateがvscodeとかで紐づかないので多少厄介でもある。
ちなみに、
pytest -s
で、「print」の結果が表示されるので試されたい。
pytest_generate_tests(フック関数)
def pytest_generate_tests(metafunc):
if "gen_param" in metafunc.fixturenames:
metafunc.parametrize("gen_param", [(1, 2, 3), (-1, 2, 1), (-1, -4, -5), (0, 0, 0)])
def test_add_pytest_generate_tests(gen_param):
x, y, result = gen_param
assert result == add(x, y)
上だけだと、あまりこのフック関数を使うメリットは少ないように見える。
ただ、「metafunc」というものがとてつもなく強力らしい。
例えば、
def pytest_generate_tests(metafunc):
if "stringinput" in metafunc.fixturenames:
metafunc.parametrize("stringinput", metafunc.config.getoption("stringinput"))
上記みたいに書くと、下記で、「hello」と「world」の2回のテストが実施できる。
pytest -q --stringinput="hello" --stringinput="world" ファイル名.py
引数で制御できるのはたまには強みになる可能性もある。
以上