この記事では、pytestで単純な足し算をする関数をパラメータ化して、テストする方法を解説します。
テストを書いていると、同じ処理を異なるデータで検証したい時があります。何も考えないと、似たコードが量産されますが、パラメータ化をすると解決できます。
パラメータ化すれば、短くシンプルなコードで、一つのテスト関数を複数のテストデータで検証できます。
pytestでのパラメータ化には、3つの方法があります。
- テスト関数をパラメータ化:最もスタンダード
- fixtureをパラメータ化:前処理、後処理を書きたい時に利用
- フック関数(pytest_generate_tests)で、パラメータ化:複雑なデータセットを書きたい時に利用
ちなみに、私の環境のバージョン情報は以下の通りです。
項目 | バージョン |
---|---|
Python | 3.10.6 |
pytest | 7.1.3 |
それでは、最後までよろしくお願いします。
テスト関数をパラメータ化する
テスト関数をパラメータ化する方法が最もスタンダードなやり方です。
テスト関数をパラメータ化するには、テスト関数の前に@pytest.mark.parametrizeを書きます。
引数にはそれぞれ、以下を設定します。
- 第1引数:テスト関数で使う引数名
- 第2関数:検証したい値のパラメータ(リスト型)
コードにすると以下のようになります。
import pytest
def addition(x, y):
"""
足し算をして、返す
"""
return x + y
@pytest.mark.parametrize(
"x, y , result",
[
(1, 2, 3),
(1, 2, 4),
(10, 23, 33)
],
)
def test_addition(x, y, result):
"""
関数をパラメータ化して、additionを検証
"""
assert result == addition(x, y)
これをpytestで実行すると、以下のようになります。
$ pytest test_func_param.py
================================================= test session starts ==================================================
platform darwin -- Python 3.10.6, pytest-7.1.3, pluggy-1.0.0
rootdir: (省略)
collected 3 items
test_func_param.py .F. [100%]
======================================================= FAILURES =======================================================
_________________________________________________ test_addition[1-2-4] _________________________________________________
x = 1, y = 2, result = 4
@pytest.mark.parametrize(
"x, y , result",
[
(1, 2, 3),
(1, 2, 4),
(10, 23, 33)
],
)
def test_addition(x, y, result):
> assert result == addition(x, y)
E assert 4 == 3
E + where 3 = addition(1, 2)
test_func_param.py:20: AssertionError
=============================================== short test summary info ================================================
FAILED test_func_param.py::test_addition[1-2-4] - assert 4 == 3
============================================= 1 failed, 2 passed in 0.14s ==============================================
2つ目のパラメータの足し算が間違っているため、2つ目のテストコードが失敗しているのが分かりますね。
fixtureをパラメータ化する
テストで前処理、後処理を書く場合、fixtureが使えます。
fixtureの書き方が分からないなら、以下にまとめています。
fixtureをパラメータ化する時は、@pytest.fixtureの引数にパラメータを設定します。
fixtureのメソッドの引数(request)にパラメータが引き渡され、パラメータごとに検証する値を設定します。
テストコードにすると、以下の通りです。
import pytest
def addition(x, y):
"""
足し算をして、返す
"""
return x + y
@pytest.fixture(params=['a', 'b', 'c'])
def fix_param(request):
"""
フィクスチャにパラメータを設定
"""
if request.param == 'a':
return (1, 2, 3)
elif request.param == 'b':
return (1, 2, 4)
elif request.param == 'c':
return (10, 23, 33)
def test_addition(fix_param):
"""
フィクスチャをパラメータ化して、additionを検証
"""
x, y, result = fix_param
assert result == addition(x, y)
では、テストコードを実行してみましょう。
$ pytest test_fixture_param.py
================================================= test session starts ==================================================
platform darwin -- Python 3.10.6, pytest-7.1.3, pluggy-1.0.0
rootdir: (省略)
collected 3 items
test_fixture_param.py .F. [100%]
======================================================= FAILURES =======================================================
___________________________________________________ test_addition[b] ___________________________________________________
fix_param = (1, 2, 4)
def test_addition(fix_param):
"""
フィクスチャをパラメータ化して、additionを検証
"""
x, y, result = fix_param
> assert result == addition(x, y)
E assert 4 == 3
E + where 3 = addition(1, 2)
test_fixture_param.py:29: AssertionError
=============================================== short test summary info ================================================
FAILED test_fixture_param.py::test_addition[b] - assert 4 == 3
============================================= 1 failed, 2 passed in 0.06s ==============================================
テスト関数をパラメータ化した時と同様の結果になっていることが分かると思います。
fixtureをパラメータ化するメリット
テスト関数と比べて、fixtureのパラメータ化は、コードが冗長になりますね。
fixtureをパラメータ化するメリットは、パラメータの値に基づいて、前処理、後処理ができることにあります。
fixtureをパラメータ化したら良いユースケースは以下の通り。
- 異なるデータベースに接続
- 異なるファイルを読み込む
- 同じデータセットで複数の関数のテストをする
ここに該当しない場合は、テスト関数をパラメータ化する方が、コードがシンプルになり、保守性が上がります。
それぞれの書き方の使い所をしっかりと把握することが大切です。
フック関数(pytest_generate_tests)で、パラメータ化する
フック関数(pytest_generate_tests)を使って、パラメータ化することができます。
フック関数はpytestの通常の処理フローを変更するために、プラグインとして使うことができます。
テストコードを実装すると、以下の通り。
def addition(x, y):
"""
足し算をして、返す
"""
return x + y
def pytest_generate_tests(metafunc):
if "param" in metafunc.fixturenames:
metafunc.parametrize("param", [(1, 2, 3), (1, 2, 4), (10, 23, 33)])
def test_addition(param):
"""
pytest_generate_testsを利用して、additionを検証
"""
print(param)
x, y, result = param
assert result == addition(x, y)
では、テストコードを実行してみましょう。
$ pytest test_generate.py
======================================================== test session starts ========================================================
platform darwin -- Python 3.10.6, pytest-7.1.3, pluggy-1.0.0
rootdir: (省略)
collected 3 items
test_generate.py .F. [100%]
============================================================= FAILURES ==============================================================
_______________________________________________________ test_addition[param1] _______________________________________________________
param = (1, 2, 4)
def test_addition(param):
"""
pytest_generate_testsを利用して、additionを検証
"""
print(param)
x, y, result = param
> assert result == addition(x, y)
E assert 4 == 3
E + where 3 = addition(1, 2)
test_generate.py:19: AssertionError
------------------------------------------------------- Captured stdout call --------------------------------------------------------
(1, 2, 4)
====================================================== short test summary info ======================================================
FAILED test_generate.py::test_addition[param1] - assert 4 == 3
==================================================== 1 failed, 2 passed in 0.16s ====================================================
これまでと同じ結果になることが分かります。
よくある質問
Python学習におすすめのコンテンツ
現役シリコンバレーエンジニアが教えるPython 3 入門 + 応用 +アメリカのシリコンバレー流コードスタイル
Udemyの講座でPythonなら、文句なしにおすすめ
- 分かりやすい言葉や具体的なコードで工夫して説明しているので、初心者でも理解できる。
- 初心者でも挫折しないように、丁寧に詳しく手順を説明している。
- 講座内で取り扱う課題は実践的なものが多く、書籍では身につかない応用力を身につけられる。
- 情報量が多いのに、講座の進み方が速いので、一回では理解が追いつかない。
- 課題の難易度が高すぎる場合がある。
- 講師のアクセントが特殊で、聞き取りにくいと感じたことがある。
テスト駆動Python 第2版
日本語で唯一、pytestだけに焦点を当てて、詳細に書かれた書籍です。
- 日本語でpytestの全てについて、解説されている唯一の書籍
- 段々とステップアップして、深くなるので、初心者でも、中級者でも、上級者でも、学びがある
- サンプルコードには、サンプルアプリが含まれているため、実践的に学べる工夫あり
- 章末にまとめがあり、復習の役に立つ
- 第7章に「どのようなテストを書くのか」についての解説があり、テストに対する考え方が深まる
- 後半になると、かなり高度な内容になるため、初心者には難しい
- タイトルに「テスト駆動開発」と書かれているが、該当部分の記述が少なく、テスト駆動開発を知りたい人は期待外れになるかも
間違えて、第1版を買わないように注意して下さい。
とても便利なpytestのパラメータ化
ここまで、pytestをパラメータ化する方法について解説しました。
復習すると、パラメータ化の方法は3つありました。
- テスト関数をパラメータ化:最もスタンダード
- fixtureをパラメータ化:前処理、後処理を書きたい時に利用
- フック関数(pytest_generate_tests)で、パラメータ化:複雑なデータセットを書きたい時に利用
上記の通り、それぞれの方法について、明確な使い時があります。
pytestでテストコードが書ければ、複数のデータパターンでテストができます。品質の高いプログラムを開発できて、現場でも重宝されます。
一度、使い方を理解すれば簡単に使えて、とても便利。自分の市場価値を高めるためにも、pytestをマスターして、スキルアップして欲しいと思います。
Pythonを勉強する時、何から勉強するか分からず、挫折します。初心者でも、中級者でも、レベルに合わせた勉強方法を分かりやすくまとめています。
コメント