Pytestでのテスト入門
18962 ワード
テストはコードを実行するコードです.Pythonプロジェクトの新機能の開発を開始すると、その要件をコードとして形式化できます.そうするとき、あなたの実装のコードを使用する方法を文書化するだけでなく、すべてのテストを自動的に実行することもできます.これを支援する1つのそのようなツールは
メールアドレスを検証する関数を書いたとしましょう.ここでは簡単にして、正規表現やDNSテストを使用しないでください.代わりに、我々はちょうど1つがあることを確認します
一方、我々の関数は 我々の関数は、実際に我々が期待するような振る舞いをすることを確認できます.
コードがどのように使われるかを文書化する 将来の変更がソフトウェアの他の部分を壊さないようにしてください あなたの機能性の可能なエッジケースについて考えてください これを行うには、すべてのテストのための新しいファイルを作成し、そこにいくつかの関数を置く.
プロジェクトディレクトリに2つのファイルがあります.
我々は今すぐに実行することができます
The
今、これらのテストケースを加えましょう
加えて、我々は新しい
私たちの小さなバリデータの例は、テストを設計することの重要性の証です.
最初にバリデーター関数を書き、いくつかのテストケースを思いついた.すぐに我々はこれらのテストケースは包括的ではないことに気づいた.代わりに、メールアドレスの検証の重要な側面を逃しました.
テスト駆動開発(TDD)について聞いたことがあります.TDDは、あなたのテストケースを最初に書いて、すべてのテストケースをカバーしていると感じる前に、機能の実装を開始しないことで、あなたの要求を正しく取得します.この考え方は常に良い考えでしたが、ソフトウェアプロジェクトが複雑さを増してきたので、時間をかけてさらに重要性を増してきました.
私はすぐに深さにそれをカバーするTDDについての別のブログ記事を書きます.
通常、プロジェクトのセットアップは、その中のバリデータ関数を持つ単一のファイルよりもはるかに複雑です.
プロジェクトのPythonパッケージ構造を持っているかもしれません.あるいは、コードがデータベースのような外部依存関係に依存する場合があります.
あなたは、異なる文脈で用語Fixtureを使用したかもしれません.たとえば、Django Webフレームワークの場合、fixtureはデータベースに読み込まれる初期データのコレクションを参照します.しかし、
このような関数を
フィクスチャを実際にテストのいずれかで使用するには、単純に引数としてフィクスチャの名前を追加します
代わりに
使用するファイルは、プロジェクトで使用する他のツールに依存します.プロジェクトをパッケージ化した場合は、
設定ファイルは、これらの3つのファイルタイプごとにほとんど同じです.
使用する
テストファイルを含む各フォルダには
The
共有備品は別として、外部フックやプラグインや修飾子を
開発中に、主にあなたの実装前にテストを書いたとき.
最も便利なコマンドラインオプションを見てみましょう.
つの特定のテストのみを実行する場合は、
すべてのテスト関数を実行するのではなく、テストコレクションのリストを持っています.
力がある
前回失敗したテストのみを実行したい場合は、
いくつかのローカル変数を使用してより複雑なテスト関数を設定すると、
次のようにテスト機能を書き直しましょう.
あなたが始めるならば
もう一つのオプションは
最新のソフトウェアプロジェクトでは、ソフトウェアはテスト駆動開発原則に従って開発され、自動化されたテストを含む連続的な統合/連続配置パイプラインを介して配信されます.
典型的なセットアップは
あなたが使用についてもっと知りたいならば
pytest
そしてそれはおそらくPythonの宇宙で最も人気のあるテストツールです.それはすべて断言している
メールアドレスを検証する関数を書いたとしましょう.ここでは簡単にして、正規表現やDNSテストを使用しないでください.代わりに、我々はちょうど1つがあることを確認します
@
テストする文字列とラテン文字、数字、および.
, -
and _
登場人物import string
def is_valid_email_address(s):
s = s.lower()
parts = s.split('@')
if len(parts) != 2:
# Not exactly one at-sign
return False
allowed = set(string.ascii_lowercase + string.digits + '.-_')
for part in parts:
if not set(part) <= allowed:
# Characters other than the allowed ones are found
return False
return True
今、我々のコードにいくつかの主張があります.たとえば、これらのメールアドレスが有効であることを確認します.[email protected]
[email protected]
[email protected]
False
電子メールアドレスのようにnot [email protected]
(スペースを含む)john.doe
(no @
) john,[email protected]
を,
) print(is_valid_email_address('[email protected]')) # True
print(is_valid_email_address('[email protected]')) # True
print(is_valid_email_address('[email protected]')) # True
print(is_valid_email_address('not [email protected]')) # False
print(is_valid_email_address('john.doe')) # False
print(is_valid_email_address('john,[email protected]')) # False
これらのメールアドレスの例はテストケースと呼ばれます.各テストケースについては、ある結果を期待します.テストツールpytest
自動化これらのアサーションをテストすることができます.これらのアサーションを書き留めてdef test_regular_email_validates():
assert is_valid_email_address('[email protected]')
assert is_valid_email_address('[email protected]')
assert is_valid_email_address('[email protected]')
def test_valid_email_has_one_at_sign():
assert not is_valid_email_address('john.doe')
def test_valid_email_has_only_allowed_chars():
assert not is_valid_email_address('john,[email protected]')
assert not is_valid_email_address('not [email protected]')
ランニングテスト
簡単な例
プロジェクトディレクトリに2つのファイルがあります.
validator.py
and test_validator.py
.我々は今すぐに実行することができます
pytest
コマンドラインから.出力は以下のようになります.============================= test session starts ==============================
platform darwin -- Python 3.9.6, pytest-7.0.1, pluggy-1.0.0
rootdir: /Users/bascodes/Code/blogworkspace/pytest-example
collected 3 items
test_validator.py ... [100%]
============================== 3 passed in 0.01s ===============================
pytest
内部に3つのテスト機能を見つけたことを知らせてくださいtest_validator.py
そして、これらのすべての機能が渡された...
).The
100%
インジケータは、我々のバリデータが期待通りに動作することを確信しているので、良い感じを与えます.しかし、導入において概説されるように、バリデータ関数は完全ではない.そして、我々のテストケースもそうです.DNSテストなしでさえ、我々は電子メールアドレスをマークしますjohn.doe@example
アドレスのように有効な[email protected]
が無効です.今、これらのテストケースを加えましょう
test_validator.py
...
def test_valid_email_can_have_plus_sign():
assert is_valid_email_address('[email protected]')
def test_valid_email_must_have_a_tld():
assert not is_valid_email_address('john.doe@example')
我々が走るならばpytest
再び、失敗したテストが表示されます.============================= test session starts ==============================
platform darwin -- Python 3.9.6, pytest-7.0.1, pluggy-1.0.0
rootdir: /Users/bascodes/Code/blogworkspace/pytest-example
collected 5 items
test_validator.py ...FF [100%]
=================================== FAILURES ===================================
_____________________ test_valid_email_can_have_plus_sign ______________________
def test_valid_email_can_have_plus_sign():
> assert is_valid_email_address('[email protected]')
E AssertionError: assert False
E + where False = is_valid_email_address('[email protected]')
test_validator.py:17: AssertionError
_______________________ test_valid_email_must_have_a_tld _______________________
def test_valid_email_must_have_a_tld():
> assert not is_valid_email_address('john.doe@example')
E AssertionError: assert not True
E + where True = is_valid_email_address('john.doe@example')
test_validator.py:20: AssertionError
=========================== short test summary info ============================
FAILED test_validator.py::test_valid_email_can_have_plus_sign - AssertionErro...
FAILED test_validator.py::test_valid_email_must_have_a_tld - AssertionError: ...
========================= 2 failed, 3 passed in 0.05s ==========================
我々が2を得たことに注意してくださいFF
アウト3に加えて...
つのテスト関数が失敗したことを示すドット.加えて、我々は新しい
FAILURES
我々のテストで失敗した点で詳細に説明する我々の出力のセクション.デバッグにはかなり役立つ.テスト設計に関するノート
私たちの小さなバリデータの例は、テストを設計することの重要性の証です.
最初にバリデーター関数を書き、いくつかのテストケースを思いついた.すぐに我々はこれらのテストケースは包括的ではないことに気づいた.代わりに、メールアドレスの検証の重要な側面を逃しました.
テスト駆動開発(TDD)について聞いたことがあります.TDDは、あなたのテストケースを最初に書いて、すべてのテストケースをカバーしていると感じる前に、機能の実装を開始しないことで、あなたの要求を正しく取得します.この考え方は常に良い考えでしたが、ソフトウェアプロジェクトが複雑さを増してきたので、時間をかけてさらに重要性を増してきました.
私はすぐに深さにそれをカバーするTDDについての別のブログ記事を書きます.
構成
通常、プロジェクトのセットアップは、その中のバリデータ関数を持つ単一のファイルよりもはるかに複雑です.
プロジェクトのPythonパッケージ構造を持っているかもしれません.あるいは、コードがデータベースのような外部依存関係に依存する場合があります.
器具
セットアップとティアダウン
あなたは、異なる文脈で用語Fixtureを使用したかもしれません.たとえば、Django Webフレームワークの場合、fixtureはデータベースに読み込まれる初期データのコレクションを参照します.しかし、
pytest
'sコンテキスト、fixtureはpytest
前と実際のテスト機能の後.このような関数を
pytest.fixture()
デコレータ.我々は、内部でこれをしますtest_validator.py
今すぐファイル.import pytest
@pytest.fixture()
def database_environment():
setup_database()
yield
teardown_database()
データベースを設定し、それを引き裂くことは同じfixtureで起こります.The yield
キーワードはどこの部分をinidcatespytest
実際のテストの実行フィクスチャを実際にテストのいずれかで使用するには、単純に引数としてフィクスチャの名前を追加します
test_validator.py
):def test_world(database_environment):
assert 1 == 1
備品からデータを取得する
代わりに
yield
fixture関数は任意の値を返すこともできます.import pytest
@pytest.fixture()
def my_fruit():
return "apple"
もう一度、テスト関数からそのフィクスチャを要求するには、fixtures名をパラメータとして提供します.def test_fruit(my_fruit):
assert my_fruit == "apple"
設定ファイル
pytest
これらのファイルからプロジェクト固有の設定を読み込むことができます.pytest.ini
tox.ini
setup.cfg
setup.cfg
ファイル.異なる環境でコードをテストするためにTOXを使用すると、pytest
の設定tox.ini
ファイル.The pytest.ini
ファイルを使用する場合は、任意の追加ツールを利用したくない場合に使用することができますがpytest
.設定ファイルは、これらの3つのファイルタイプごとにほとんど同じです.
使用する
pytest.ini
and tox.ini
:[pytest]
addopts = -rsxX -l --tb=short --strict
**使用している場合setup.cfg
ファイルは、唯一の違いは[pytest]
セクションtool:
以下のように:[tool:pytest]
addopts = -rsxX -l --tb=short --strict
懺悔する。パイ
テストファイルを含む各フォルダには
conftest.py
読み込むファイルpytest
. これは、これらの異なるファイル間で共有できるようにカスタムの備品を配置するのに良い場所です.The
conftest.py
ファイル( s )はpytest
プロジェクトごとに.共有備品は別として、外部フックやプラグインや修飾子を
PATH
使用するpytest
テストと実装コードを発見する.CLI / PDB
開発中に、主にあなたの実装前にテストを書いたとき.
pytest
デバッグのための有益なツールです.最も便利なコマンドラインオプションを見てみましょう.
つのテストを実行するだけ
つの特定のテストのみを実行する場合は、
test_
ファイルが入っており、その関数の名前は以下の通りです:pytest test_validator.py::test_regular_email_validates
収集のみ
すべてのテスト関数を実行するのではなく、テストコレクションのリストを持っています.
pytest --collect-only
============================= test session starts ==============================
platform darwin -- Python 3.9.6, pytest-7.0.1, pluggy-1.0.0
rootdir: /Users/bascodes/Code/blogworkspace/pytest-example
collected 5 items
<Module test_validator.py>
<Function test_regular_email_validates>
<Function test_valid_email_has_one_at_sign>
<Function test_valid_email_has_only_allowed_chars>
<Function test_valid_email_can_have_plus_sign>
<Function test_valid_email_must_have_a_tld>
========================== 5 tests collected in 0.01s ==========================
最初のエラーで終了する
力がある
pytest
失敗した後のテストを停止するには、次の手順に従います.pytest -x
最後に失敗したテストのみを実行する
前回失敗したテストのみを実行したい場合は、
--lf
フラグ:pytest --lf
すべてのテストを実行する
pytest --ff
出力中のローカル変数の値を表示する
いくつかのローカル変数を使用してより複雑なテスト関数を設定すると、
pytest
これらのローカル変数を-l
フラグ.次のようにテスト機能を書き直しましょう.
...
def test_valid_email_can_have_plus_sign():
email = '[email protected]'
assert is_valid_email_address('[email protected]')
...
Then,pytest -l
を返します.============================= test session starts ==============================
platform darwin -- Python 3.9.6, pytest-7.0.1, pluggy-1.0.0
rootdir: /Users/bascodes/Code/blogworkspace/pytest-example
collected 5 items
test_validator.py ...FF [100%]
=================================== FAILURES ===================================
_____________________ test_valid_email_can_have_plus_sign ______________________
def test_valid_email_can_have_plus_sign():
email = '[email protected]'
> assert is_valid_email_address('[email protected]')
E AssertionError: assert False
E + where False = is_valid_email_address('[email protected]')
email = '[email protected]'
test_validator.py:18: AssertionError
_______________________ test_valid_email_must_have_a_tld _______________________
def test_valid_email_must_have_a_tld():
> assert not is_valid_email_address('john.doe@example')
E AssertionError: assert not True
E + where True = is_valid_email_address('john.doe@example')
test_validator.py:21: AssertionError
=========================== short test summary info ============================
FAILED test_validator.py::test_valid_email_can_have_plus_sign - AssertionErro...
FAILED test_validator.py::test_valid_email_must_have_a_tld - AssertionError: ...
========================= 2 failed, 3 passed in 0.09s ==========================
PyTestを使用したテスト
pdb
はPythonに組み込まれたコマンドラインデバッガです.テスト関数のコードをデバッグするにはPyTestを使用できます.あなたが始めるならば
pytest
with --pdb
, それは始まりますpdb
テストの例外が発生した直後のデバッグセッション.ほとんどの場合、例外を送出する前にコードの各行を検査したい場合は特に役に立ちません.もう一つのオプションは
--trace
フラッグフォーpytest
各テスト関数の最初の行でブレークポイントを設定します.テストがたくさんあるなら、これは少し不便になるかもしれません.それで、デバッグ目的のために、良い組合せはそうです--lf --trace
デバッグセッションを開始するpdb
失敗した最後のテストの先頭にpytest --lf --trace
============================= test session starts ==============================
platform darwin -- Python 3.9.6, pytest-7.0.1, pluggy-1.0.0
rootdir: /Users/bascodes/Code/blogworkspace/pytest-example, configfile: pytest.ini
collected 2 items
run-last-failure: rerun previous 2 failures
test_validator.py
>>>>>>>>>>>>>>>>>>>> PDB runcall (IO-capturing turned off) >>>>>>>>>>>>>>>>>>>>>
> /Users/bascodes/Code/blogworkspace/pytest-example/test_validator.py(17)test_valid_email_can_have_plus_sign()
-> email = '[email protected]'
(Pdb)
シー・シーディー
最新のソフトウェアプロジェクトでは、ソフトウェアはテスト駆動開発原則に従って開発され、自動化されたテストを含む連続的な統合/連続配置パイプラインを介して配信されます.
典型的なセットアップは
main
/master
すべてのテスト関数が通過しない限り、分岐は拒否されます.あなたが使用についてもっと知りたいならば
pytest
CI/CD環境では、私はそのトピックの新しい記事を計画しているように調整滞在.Reference
この問題について(Pytestでのテスト入門), 我々は、より多くの情報をここで見つけました https://dev.to/bascodes/a-gentle-introduction-to-testing-with-pytest-3fakテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol