Python WebAcademy Blog

pytest 9.2がリリース。parametrizeの書き間違いがわかりやすいエラーに、差分の読み方の説明も付いたニュースを初心者向けに解説

|

2026年10月27日、Pythonのテストの定番ツールpytestの9.2.0が公開されました。parametrizeの引数の書き間違いが意味のわかるエラーになり、失敗したときの差分には+と-の意味の説明が付きました。入れ子のデータをpytest.approxに渡したときの扱いも変わっています。9.1.1と9.2.0で同じテストを動かした結果とともに整理します。

2026年10月27日、Pythonのテストで最もよく使われているツールpytestの9.2.0が公開されました。6月の9.1.1から、およそ4か月ぶりの新しい版です。

今回は、初心者がつまずきやすいところを助けてくれる変更が目立ちます。parametrizeの書き間違いが、意味のわかるエラーになりました。

テストが失敗したときの差分にも、+と-が何を表すかの説明が付いています。今回は、9.1.1と9.2.0で同じテストを動かしながら、何が変わったのかを見ていきます。

まずは9.2で何が変わったのかを整理しよう

最初に、9.2.0の主な変更を表にまとめます。内容は、pytestの公式リポジトリにある変更履歴changelog.rstにもとづいています。

分類 主な変更
互換性を壊す変更 parametrizeのindirect、ids、scopeをキーワード専用に
互換性を壊す変更 プラグインを読み込めないときの終了コードを整理
新機能 Full diffに、+と-の意味の説明を表示
新機能 長い文字列のパラメーターからテスト名を作る方法を選べる設定
改善 アサーションの書き換え結果のキャッシュを、時刻ではなく中身で判定
不具合の修正 入れ子のデータを渡したpytest.approxがTypeErrorを出すように

PyPIの記録によると、9.2.0が必要とするPythonは、これまでどおり3.10以上です。最近は3.10を外すライブラリが多い中、pytestはまだ3.10に対応しています。

pytestそのものの使い方は、こちらで紹介しています。【関連記事】pytest入門|Pythonでテストを書く基本

parametrizeの書き間違いが、わかりやすいエラーに

まずは、互換性を壊す変更から見ていきましょう。parametrizeは、1つのテスト関数を、いくつもの値の組み合わせで繰り返し動かす仕組みです。

変更履歴によると、parametrizeのindirect、ids、scopeの3つの引数が、キーワード専用になりました。つまり、ids=[...]のように、名前を付けて渡す必要があります。

よくある書き間違い

変更履歴では、よくある間違いの例として、引数の名前を別々の文字列で書いてしまうケースが挙げられています。実際に、その書き方を試してみましょう。

import pytest


@pytest.mark.parametrize("a", "b", [(1, 2)])
def test_add(a, b):
    assert a < b

本当は"a, b"と1つの文字列にまとめるべきところを、"a"と"b"に分けてしまっています。9.1.1と9.2.0を、それぞれ新しい仮想環境に入れ、手元のPython 3.11で動かした結果です。

pytest 9.1.1
In test_param.py::test_add: indirect fixture '(1, 2)' doesn't exist

pytest 9.2.0
TypeError: Metafunc.parametrize() takes 3 positional arguments but 4 positional arguments (and 1 keyword-only argument) were given

9.1.1では、(1, 2)という名前のフィクスチャがない、というエラーでした。値として渡したつもりの[(1, 2)]が、3番目のindirectという引数に入ってしまったためです。

これでは、何を間違えたのか見当がつきませんよね。9.2.0では、位置で渡せる引数の数を超えているというTypeErrorになり、引数の数がおかしいことがすぐわかります。

正しい書き方

正しくは、引数の名前を1つの文字列にまとめ、idsなどは名前を付けて渡します。9.2.0で試した書き方です。

import pytest


@pytest.mark.parametrize("a, b", [(1, 2), (3, 5)], ids=["small", "large"])
def test_add(a, b):
    assert a < b

pytest -vで実行すると、次のように2つのテストとして動きました。

test_param_ok.py::test_add[small] PASSED
test_param_ok.py::test_add[large] PASSED

idsで付けた名前が、角かっこの中に表示されています。これまでidsを名前なしで渡していた方は、ids=を付けるように直しておきましょう。

長い文字列のテスト名は短くなった

parametrizeでは、渡した値から、角かっこの中のテスト名が自動で作られます。変更履歴によると、9.2.0では新しい設定parametrize_long_str_id_strategyが加わり、既定のshortでは、100文字を超える文字列は引数名と番号の形に置き換わります。

150文字の文字列を渡したテストで、pytest --collect-only -qを実行すると、テスト名は次のようになりました。

版 2つ目のテストの名前
9.1.1 test_length[xxxx…](150文字がそのまま並ぶ)
9.2.0 test_length[text1]

長い値をそのまま名前にすると、画面からはみ出して読みにくくなります。CIの結果でテスト名を探すときにも、短いほうが扱いやすいでしょう。

差分の+と-に説明が付いた

続いて、新機能です。変更履歴によると、Full diffという差分の表示に、+と-の記号が何を表すかの説明が付きました。

実際に失敗させてみた

リストの比較が失敗するテストを用意して、pytest -vvで詳しい差分を表示させてみます。

def test_fruits():
    assert ["apple", "banana", "melon"] == ["apple", "orange", "melon"]

9.1.1と9.2.0で、差分の部分を比べた結果です。

pytest 9.1.1
Full diff:
  [
      'apple',
-     'orange',
+     'banana',
      'melon',
  ]

pytest 9.2.0
Full diff: (-: missing in left side, +: extra in left side)
  [
      'apple',
-     'orange',
+     'banana',
      'melon',
  ]

9.2.0では、Full diffの横に、-は左側に足りないもの、+は左側に余計なもの、という説明が加わりました。ここでいう左側とは、==の左に書いた値、つまり実際の結果のことです。

なぜ嬉しいのか

差分の+と-は、どちらが期待した値で、どちらが実際の値なのか、慣れないうちは混乱しがちです。説明が毎回表示されるので、記号の意味を覚えていなくても読めるようになりました。

assertの書き方や、失敗したときの表示の読み方は、こちらで詳しく紹介しています。【関連記事】pytestのassert文の使い方解説

pytest.approxに入れ子のデータを渡すとエラーに

小数の比較で使うpytest.approxにも、大事な修正が入っています。approxは、0.1+0.2のように、ごくわずかな誤差が出る計算を、許容範囲付きで比べるための関数です。

変更履歴によると、これまでは、リストの中に辞書を入れたような入れ子のデータを渡すと、エラーにならずに受け付けられていました。ところが、比べると必ず等しくないと判断され、許容範囲が黙って無視されていたそうです。

2つの版で比べてみた

実際に、リストの中に辞書が入ったデータで試しました。

import pytest


def test_scores():
    assert [{"score": 0.1 + 0.2}] == pytest.approx([{"score": 0.3}])

実行した結果の、エラーの部分です。9.1.1の表示は、要点だけに短くしています。

pytest 9.1.1
AssertionError: assert [{'score': 0....000000000004}] == approx([{'score': 0.3}])
(pytest_assertion plugin: representation of details failed: ...)

pytest 9.2.0
TypeError: pytest.approx() does not support nested data structures: {'score': 0.3} at index 0

9.1.1では、テストが失敗したうえに、詳しい表示を作る段階でも内部のエラーが出ていました。9.2.0では、approxは入れ子のデータに対応していない、とはっきり教えてくれます。

入れ子のデータを比べたいときは

入れ子のデータを比べたいときは、中の値ごとにapproxを使います。たとえばresult[0]["score"] == pytest.approx(0.3)のように、小数の部分だけを取り出して比べるとよいでしょう。

CIでテストが速くなるかもしれない変更

もう1つ、実務で効いてきそうな改善も紹介します。pytestは、assertの失敗をわかりやすく表示するために、テストのファイルを読み込むときに書き換えています。

書き換えた結果は、__pycache__というフォルダにキャッシュとして保存されます。変更履歴によると、このキャッシュが使えるかどうかを、ファイルの更新時刻ではなく、中身から計算したハッシュ値で判断するようになりました。

なぜCIで効くのか

GitHub Actionsのような、コードを変更するたびに自動でテストを動かす仕組みを、CI(継続的インテグレーション)と呼びます。CIでは、毎回リポジトリを取り出し直すので、すべてのファイルの更新時刻が新しくなります。

変更履歴によると、そのせいで、保存しておいたキャッシュがまるごと捨てられ、すべてのテストファイルが毎回書き換え直されていたそうです。中身で判断するようにしたことで、1ファイルあたりおよそ15マイクロ秒の計算と引き換えに、キャッシュが生き残るようになったと説明されています。

GitHub Actionsでテストを自動で動かす方法は、こちらで紹介しています。【関連記事】GitHub Actions入門

そのほかの変更

ほかにも、たくさんの改善と修正が入っています。初心者にも関係しそうなものを、表にまとめます。

変更 中身
-cの扱い 存在しない設定ファイルを指定すると、使い方の誤りとしてエラーに
strict_markers 有効なとき、-mで指定したマーカー名も登録済みかを確かめる
tmp_path 一時フォルダが多いときに、どんどん遅くなる問題を修正
pytest.toml [pytest]の表がないまま書いた設定を、黙って無視せずエラーに
yield_fixture 古い書き方として、pytest 10か11で取り除く予定に

どれも、黙って無視されていた間違いを、その場で教えてくれる方向の変更です。

上げる前にやっておきたいこと

最後に、pytestを9.2.0へ上げる前に確かめておきたいことを整理します。

順番 確認すること
1 parametrizeのids、indirect、scopeを、名前なしで渡していないか
2 pytest.approxに、入れ子のリストや辞書を渡していないか
3 -cで指定している設定ファイルが、本当に存在するか
4 使うpytestの版を、requirements.txtなどで固定しているか

私は10年ほどエンジニアとして開発に関わってきましたが、parametrizeの引数の名前を分けて書いてしまい、意味のわからないフィクスチャのエラーで30分ほど悩んだことがあります。今回の変更で、同じところでつまずく人はぐっと減るはずです。

まとめ

2026年10月27日、pytest 9.2.0が公開されました。parametrizeの書き間違いがわかりやすいTypeErrorになり、差分には+と-の意味の説明が付き、入れ子のデータを渡したapproxもはっきりエラーを出すようになっています。

どれも、テストを書く人がつまずきにくくなる、嬉しい変更です。上げたあとにエラーが出たら、それは今まで見過ごしていた書き間違いかもしれません。

ここまでお読みいただきありがとうございました。

参考情報

次のアクション

記事で学んだ内容を実際に動かしてみよう

Python WebAcademyでは、ブラウザ上でコードを書きながら基礎から実践まで体系的に学べます。

Python WebAcademyの学習画面

あわせて読む

関連記事

ブログ一覧へ

Python学習ロードマップ

まずはこの3講座から

記事で気になったテーマを、順番に手を動かしながら学べます。

ロードマップを見る