Pytestで例外が発生するかどうかをチェックする方法
TLドクター
時間は貴重な資源であるので、私はあなたを浪費しません.ここでは、どのように例外を発生させると主張することができますどのように
pytest
.使用方法
pytest.raises
import pytest
def test_raises_exception():
with pytest.raises(ZeroDivisionError):
1 / 0
そして、どのようにあなたがアサートするかは例外です.解決法:あなたのコードを
try/except
ブロックし、コードが発生する場合は、それをキャッチし、素敵なメッセージを印刷することができます.pytest
あなたはそれをキャッチしない場合でも、テストを失敗させるに十分なスマートですが、メッセージをあなたのテストクリーナーになります.def my_division_function(a, b):
return a / b
def test_code_raises_no_exception():
"""
Assert your python code raises no exception.
"""
try:
my_division_function(10, 5)
except ZeroDivisionError as exc:
assert False, f"'10 / 5' raised an exception {exc}"
そして、それは、あなたがもっと知りたい場合は、沿って従ってください.導入
このチュートリアルでは、使用方法を学びます
pytest
です.pytest.raises
これらの例の例を挙げてください.目次
例外が発生すると主張する方法
この節では、コードが例外を発生させるという主張をどのようにするかを示します.これは頻繁に使用するケースであり、時々トリッキーです.あなたが使っているなら、素晴らしいことは
pytest
あなたは慣用的でクリーンな方法でそれを行うことができます.辞書のキーをチェックする関数があることを想像しましょう.キーが存在しない場合は
KeyError
. ご覧のように、これは非常に一般的であり、ユーザーにエラーについて多くのことを伝えません.我々は、フィールドに応じて別のメッセージを使用して、カスタムの例外を高めることによってそれをきれいにすることができます.import pytest
class MissingCoordException(Exception):
"""Exception raised when X or Y is not present in the data."""
class MissingBothCoordException(Exception):
"""Exception raised when both X and Y are not present in the data."""
def sum_x_y(data: dict) -> str:
return data["x"] + data["y"]
さて、これをテストする時間.どうすればいいのかpytest
?このコードは意図的に間違っています.実際には、TDDのように最初にテスト失敗を見たい.テスト失敗を見た後、我々の実装を修正し、テストを再実行できます.
def test_sum_x_y_missing_both():
data = {"irrelevant": 1}
with pytest.raises(MissingBothCoordException):
sum_x_y(data)
次に、次の出力を取得します.============================ FAILURES ============================
________________ test_sum_x_y_missing_both _________________
def test_sum_x_y_missing_both():
data = {"irrelevant": 1}
with pytest.raises(MissingBothCoordException):
> sum_x_y(data)
test_example.py:33:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
data = {'irrelevant': 1}
def sum_x_y(data: dict) -> str:
> return data["x"] + data["y"]
E KeyError: 'x'
test_example.py:27: KeyError
==================== short test summary info =====================
FAILED test_example.py::test_sum_x_y_missing_both - KeyEr...
======================= 1 failed in 0.02s ========================
OK、これは意味をなす、今それを修正する時間です.データをチェックするdict
両方ともx
and y
, そうでなければ我々はMissingBothCoordException
.def sum_x_y(data: dict) -> str:
if "x" not in data and "y" not in data:
raise MissingBothCoordException("Both x and y coord missing.")
return data["x"] + data["y"]
そして、我々がテストを再実行するとき、それは通ります.test_example.py . [100%]
======================= 1 passed in 0.01s ========================
すごい!そして、それはかなりそれです.これは例外が発生したかどうかをチェックする方法ですpytest
. 次のセクションでは、我々は我々の機能を改善するつもりです、そして、我々はもう一つのテストを必要とします.例外メッセージとタイプをアサートする方法
このセクションでは、我々は改善されます
sum_x_y
関数とテスト.例外メッセージをチェックすることでテストをより堅牢にする方法を示します.それを念頭に置きましょう
sum_x_y
関数.def sum_x_y(data: dict) -> str:
if "x" not in data and "y" not in data and "extra" not in data:
raise MissingBothCoordException("Both X and Y coord missing.")
if "x" not in data:
raise MissingCoordException("The Y coordinate is not present in the data.")
if "y" not in data:
raise MissingCoordException("The Y coordinate is not present in the data.")
return data["x"] + data["y"]
新しいテストは次のようになります.def test_sum_x_y_has_x_missing_coord():
data = {"extra": 1, "y": 2}
with pytest.raises(MissingCoordException):
sum_x_y(data)
そして、それは通過します!$ poetry run pytest -k test_sum_x_y_has_x_missing_coord
====================== test session starts =======================
collected 2 items / 1 deselected / 1 selected
test_example.py . [100%]
================ 1 passed, 1 deselected in 0.01s =================
しかし、それは少し壊れやすいです.あなたがそれに気づいていなかった場合は"x"
が見つからない場合、例外メッセージは次のようになります."The Y coordinate is not present in the data."
. これはバグです、そして、それを見つける1つの方法は我々が正しいメッセージを返すことによってあります.ありがたいことに.pytest
簡単に行うことができます.テストを再評価してメッセージを考慮すると、次の出力が得られます.
def test_sum_x_y_has_x_missing_coord():
data = {"extra": 1, "y": 2}
with pytest.raises(MissingCoordException) as exc:
sum_x_y(data)
assert "The X coordinate is not present in the data." in str(exc.value)
============================ FAILURES ============================
_____________ test_sum_x_y_has_x_missing_coord _____________
def test_sum_x_y_has_x_missing_coord():
data = {"extra": 1, "y": 2}
with pytest.raises(MissingCoordException) as exc:
sum_x_y(data)
> assert "The X coordinate is not present in the data." in str(exc.value)
E AssertionError: assert 'The X coordinate is not present in the data.' in 'The Y coordinate is not present in the data.'
E + where 'The Y coordinate is not present in the data.' = str(MissingCoordException('The Y coordinate is not present in the data.'))
E + where MissingCoordException('The Y coordinate is not present in the data.') = <ExceptionInfo MissingCoordException('The Y coordinate is not present in the data.') tblen=2>.value
test_example.py:32: AssertionError
==================== short test summary info =====================
FAILED test_example.py::test_sum_x_y_has_x_missing_coord
======================= 1 failed in 0.02s ========================
それはまさに私たちが望むものです.コードを修正してテストを再実行しましょう.def sum_x_y(data: dict) -> str:
if "x" not in data and "y" not in data and "extra" not in data:
raise MissingBothCoordException("Both X and Y coord missing.")
if "x" not in data:
raise MissingCoordException("The X coordinate is not present in the data.")
if "y" not in data:
raise MissingCoordException("The Y coordinate is not present in the data.")
return data["x"] + data["y"]
結果.$ poetry run pytest test_example.py::test_sum_x_y_has_x_missing_coord
====================== test session starts =======================
platform linux -- Python 3.8.5, pytest-6.1.1, py-1.9.0, pluggy-0.13.1
rootdir: /home/miguel/projects/tutorials/pytest-raises
collected 1 item
test_example.py . [100%]
======================= 1 passed in 0.01s ========================
これは可能ですpytest.raises
返り値ExceptionInfo
フィールドを含むオブジェクトtype
, value
, traceback
and many others . 我々が主張したいならばtype
, 我々は、これらの線に沿って何かをすることができました.def test_sum_x_y_has_x_missing_coord():
data = {"extra": 1, "y": 2}
with pytest.raises(MissingCoordException) as exc:
sum_x_y(data)
assert "The X coordinate is not present in the data." in str(exc.value)
assert exc.type == MissingCoordException
しかし、我々はすでに使用してpytest.raises
それで、私はこのようなタイプを少し冗長であると主張すると思います.この時はいつ役に立つのですか.これは私たちがより一般的な例外をアサートしている場合に便利ですpytest.raises
そして、正確な例外をチェックしたい.例えば:def test_sum_x_y_has_x_missing_coord():
data = {"extra": 1, "y": 2}
with pytest.raises(Exception) as exc:
sum_x_y(data)
assert "The X coordinate is not present in the data." in str(exc.value)
assert exc.type == MissingCoordException
メッセージをアサートするもう一つの方法はmatch
指定したいパターンの引数.以下の例は公式から取ったものですpytest
docs .>>> with raises(ValueError, match='must be 0 or None'):
... raise ValueError("value must be 0 or None")
>>> with raises(ValueError, match=r'must be \d+$'):
... raise ValueError("value must be 42")
ご覧のように、期待される例外が発生した場合でも、メッセージがregexパターンに一致するかどうかを確認できます.例外が発生しないと主張する方法
このチュートリアルの最後のセクションでは、もう一つの一般的な使用例について説明します.例外がスローされないことをアサートする方法.我々がそうすることができる1つの方法は、A
try / except
. それが例外を上げるならば、我々はそれを捕えて、偽を主張します.def test_sum_x_y_works():
data = {"extra": 1, "y": 2, "x": 1}
try:
sum_x_y(data)
except Exception as exc:
assert False, f"'sum_x_y' raised an exception {exc}"
このテストを実行すると、パスします.$ poetry run pytest test_example.py::test_sum_x_y_works
====================== test session starts =======================
collected 1 item
test_example.py . [100%]
======================= 1 passed in 0.00s ========================
さて、テスト失敗を見ることができるように意図的なバグを作りましょう.我々は、我々の機能を変えるために、我々を変えますValueError
結果を返す前に.def sum_x_y(data: dict) -> str:
if "x" not in data and "y" not in data and "extra" not in data:
raise MissingBothCoordException("'extra field and x / y coord missing.")
if "x" not in data:
raise MissingCoordException("The X coordinate is not present in the data.")
if "y" not in data:
raise MissingCoordException("The Y coordinate is not present in the data.")
raise ValueError("Oh no, this shouldn't have happened.")
return data["x"] + data["y"]
そして、テストを再実行します. def test_sum_x_y_works():
data = {"extra": 1, "y": 2, "x": 1}
try:
sum_x_y(data)
except Exception as exc:
> assert False, f"'sum_x_y' raised an exception {exc}"
E AssertionError: 'sum_x_y' raised an exception Oh no, this shouldn't have happened.
E assert False
test_example.py:52: AssertionError
==================== short test summary info =====================
FAILED test_example.py::test_sum_x_y_works - AssertionErr...
======================= 1 failed in 0.02s ========================
動く!我々のコードはValueError
そして、テストは失敗しました!結論
それは今日、人々のためだ!あなたが何か新しいことを学んだことを願っています.例外をテストする方法を知ることは重要なスキルです.道
pytest
それは、Imhoよりきれいですunittest
そして、より冗長な.この記事では、あなたのコードが期待される例外を発生させると主張するだけでなく、提起されるべきでないときにアサートする方法を示しました.最後に、私たちは、例外メッセージがあなたが予想するものであるかどうかチェックする方法を見ました.閉じるこの動画はお気に入りから削除されています
また会いましょう!
Reference
この問題について(Pytestで例外が発生するかどうかをチェックする方法), 我々は、より多くの情報をここで見つけました https://dev.to/miguendes/how-to-check-if-an-exception-is-raised-or-not-with-pytest-3ljkテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol