pytest とは
pytestは、Pythonのテストフレームワークの1つで、Pythonのコードをテストするためのツールです。以下は、pytestの主な特徴についての説明です。
-
シンプルで使いやすい
pytestは、簡潔で読みやすいコードでテストを記述することができます。また、テストの自動検出やパラメータ化などの機能があり、より簡単なテストの記述が可能です。 -
fixture
pytestは、fixtureと呼ばれる機能を提供します。fixtureは、テストの前処理や後処理などを実行するための機能で、テストコードの重複を減らすことができます。 -
プラグインアーキテクチャ
pytestは、プラグインアーキテクチャを採用しており、ユーザーが独自のプラグインを作成することができます。これにより、pytestの機能を拡張したり、自分のプロジェクトに適した機能を追加したりすることができます。 -
テストランナー
pytestは、複数のテストを実行するためのランナーを提供します。テストランナーは、テストの収集、実行、レポートの生成などを行います。 -
多様なテストスタイル
pytestは、様々なテストスタイルに対応しています。例えば、unittestスタイルのテスト、BDDスタイルのテスト、doctestスタイルのテストなどに対応しています。 -
多言語対応
pytestは、Pythonだけでなく、他の言語のテストもサポートしています。例えば、CやC++ のテストを実行するためのプラグインがあります。 -
テストカバレッジ
pytestは、テストカバレッジを測定するためのプラグインも提供しています。テストカバレッジとは、コードのどの部分がテストされたかを示す指標で、テストカバレッジが高いほど、コードの品質が高いとされています。 -
クラスやメソッドレベルのスコープ
pytestは、テストのスコープを柔軟に設定することができます。例えば、クラスレベルのfixtureや、メソッドレベルのテストなどを定義することができます。 -
テストの並列実行
pytestは、テストを並列実行することができます。これにより、テストの実行時間を短縮することができます。 -
外部のテストランナーとの統合
pytestは、外部のテストランナーと統合することができます。例えば、JenkinsやTravis CIなどのCI/CDツールと統合することができます。 -
パラメータ化テスト
pytestは、パラメータ化テストをサポートしています。パラメータ化テストとは、同じテストを複数の入力値に対して実行することで、網羅的なテストを行う手法です。pytestでは、@pytest.mark.parametrize
デコレータを使用してパラメータ化テストを定義することができます。 -
テストのスキップやスキップ条件の設定
pytestでは、テストをスキップすることができます。また、スキップ条件を指定することもできます。例えば、特定のOSやPythonバージョンでのみテストを実行する場合などに有用です。 -
フック関数
pytestでは、テストの実行前や実行後にフック関数を実行することができます。これにより、テストの前処理や後処理を柔軟に設定することができます。 -
カスタムアサーション
pytestでは、独自のアサーションを定義することができます。これにより、アプリケーションやライブラリの仕様に合わせたアサーションを定義することができます。 -
優れたレポーティング
pytestは、豊富なレポーティング機能を提供しています。テストの実行結果をHTML、XML、JSONなどの形式で出力することができ、視覚的にテスト結果を確認することができます。
pytestは、Pythonのアプリケーションやライブラリのテストに広く使用されており、多くの開発者によって支持されています。また、pytestは、他のPythonのテストフレームワーク(例えば、unittestやnose)との統合も可能です。
pytest の使い方
pytestを使ってPythonプロジェクトのテストを実行するには、次の手順に従います。
- pytestをインストールする
- テストファイルを作成する
- テストを実行する
- オプションの使用
pytest をインストールする
次のコマンドでpytestをインストールします。
$ pip install pytest
テストファイルを作成する
テストファイルは、ファイル名が"test*"
で始まり、.py
で終わる必要があります。また、テスト関数は、"test*"
で始める必要があります。例えば、次のようなテストファイルを作成します。
def test_addition():
assert 1 + 2 == 3
def test_subtraction():
assert 5 - 3 == 2
テストを実行する
コマンドラインで、次のようにpytestコマンドを実行します。pytestは、カレントディレクトリ次の全てのテストファイルを自動的に検出して実行します。
$ pytest
テストが正常に実行されると、次のような出力が表示されます。
============================= test session starts =============================
platform win32 -- Python 3.7.6, pytest-6.2.2, py-1.10.0, pluggy-0.13.1
rootdir: C:\projects\pytest
collected 2 items
test_sample.py .. [100%]
============================== 2 passed in 0.04s ==============================
この例では、2つのテストが実行され、全てが合格しました。
オプションの使用
pytestには、様々なオプションがあります。例えば、次のようにオプションを指定して、レポート形式を変更することができます。
$ pytest --junitxml=junit.xml
この例では、テスト結果をjunit.xml
というファイルに書き出します。このファイルは、CI/CDツールで利用することができます。
テストのパラメータ化
pytestでは、同じテストを複数回実行することができます。例えば、異なる引数を使用して、同じテストを複数回実行することができます。例えば、次のようにして、異なる引数を使用して、同じテストを複数回実行することができます。
import pytest
@pytest.mark.parametrize("dividend, divisor, expected_quotient", [(10, 2, 5), (12, 3, 4)])
def test_division(dividend, divisor, expected_quotient):
assert dividend / divisor == expected_quotient
この例では、@pytest.mark.parametrize
デコレータを使用して、3つの引数(dividend
、divisor
、expected_quotient
)を指定し、それぞれの値をタプルで指定しています。テストは、それぞれのタプルの値を使用して、複数回実行されます。
fixture
pytestには、テストコードの再利用性を高めるために、fixtureという機能があります。fixtureは、テストコードの前処理や後処理を定義することができ、テストコード内で使用されるオブジェクトを提供することができます。
fixtureは、pytest.fixture
デコレータを使用して定義されます。以下は、単純なfixtureの例です。
import pytest
@pytest.fixture
def my_fixture():
preprocess() # preprocess test code within this function
yield obj # obj is the object used in the test code
postprocess() # post-process the test code within this function
この例では、my_fixture
という名前のfixtureを定義しています。このfixtureは、yield文でobj
というオブジェクトを返します。テストコードでは、my_fixture
を引数として受け取ることができます。
def test_my_test(my_fixture):
# test using the object provided by my_fixture
この例では、test_my_test
という名前のテストコードを定義しています。このテストコードは、my_fixture
というfixtureを引数として受け取っています。my_fixture
が提供するオブジェクトを使用してテストを行うことができます。
fixtureは、pytestがテストコードを実行する前に自動的に呼び出され、テストコードの前処理を行います。テストコードが完了した後、fixtureは自動的に後処理を行います。fixtureは、テストコード間でオブジェクトを共有することができ、コードの再利用性を高めることができます。
fixture のパラメータ化
fixtureには、パラメータを渡すこともできます。これにより、異なるパラメータを持つ複数のオブジェクトを返すことができます。
import pytest
@pytest.fixture(params=[1, 2, 3])
def my_fixture(request):
return request.param
この例では、my_fixture
という名前のfixtureを定義しています。このfixtureは、params
オプションを使用して、1, 2, 3という3つのパラメータを持つことができます。テストコードでは、my_fixture
を引数として受け取ることができます。このfixtureは、各パラメータごとにオブジェクトを返します。
def test_my_test(my_fixture):
assert my_fixture > 0
この例では、test_my_test
という名前のテストコードを定義しています。このテストコードは、my_fixture
というfixtureを引数として受け取っています。my_fixture
は、1, 2, 3という3つのパラメータに対してそれぞれオブジェクトを返すため、このテストコードは3回実行されます。
fixture の依存関係
fixtureは、他のfixtureに依存することができます。これにより、テストコードが必要とする複数のオブジェクトを一度に提供することができます。
import pytest
@pytest.fixture
def obj1():
return ...
@pytest.fixture
def obj2(obj1):
return ...
@pytest.fixture
def obj3(obj1, obj2):
return ...
この例では、3つのfixtureを定義しています。obj1
は独立したfixtureであり、obj2
はobj1
に依存するfixtureです。また、obj3
はobj1
とobj2
に依存するfixtureです。テストコードでは、obj3
を引数として受け取ることができます。obj3
は、obj1
とobj2
が提供するオブジェクトを使用して生成されます。
def test_my_test(obj3):
...
この例では、test_my_test
という名前のテストコードを定義しています。このテストコードは、obj3
というfixtureを引数として受け取っています。obj3
は、obj1
とobj2
が提供するオブジェクトを使用して生成されます。
fixture のスコープ
fixtureは、テストセットの異なる部分で再利用することができます。fixtureには、次のスコープがあります。
スコープ | 説明 |
---|---|
function | テストコードの実行前に実行され、その後削除される(デフォルト値)。 |
class | 同じクラス内の全てのテストコードで再利用される。 |
module | 同じモジュール内の全てのテストコードで再利用される。 |
session | pytest が実行される間、全てのテストコードで再利用される。 |
スコープを指定するには、fixtureにscope
オプションを使用します。
import pytest
@pytest.fixture(scope="module")
def my_fixture():
return ...
この例では、my_fixture
という名前のfixtureを定義しています。このfixtureは、scope
オプションに"module"
を指定しています。つまり、このfixtureは同じモジュール内の全てのテストコードで再利用されます。
fixture のキャッシュ
fixtureは、同じテストコード内で複数回呼び出されることがあります。pytestは、同じfixtureを複数回実行する代わりに、最初の呼び出しの結果をキャッシュします。これにより、fixtureの実行時間を節約できます。
fixtureのキャッシュを無効にするには、autouse
オプションを使用します。
import pytest
@pytest.fixture(autouse=True)
def my_fixture():
return ...
この例では、my_fixture
という名前のfixtureを定義しています。このfixtureは、autouse
オプションにTrue
を指定しています。つまり、このfixtureは、テストコードに明示的に引数として渡す必要がなく、自動的に実行されます。また、このfixtureは、キャッシュされません。
fixture の自動検出
pytestは、デフォルトでconftest.py
という名前のファイルを自動的に検出します。conftest.py
に定義されたfixtureは、そのファイルを含むディレクトリ次の全てのテストコードから参照することができます。これにより、fixtureの再利用性を高めることができます。
プラグイン
pytestには、様々なプラグインが用意されており、ユーザーが自由に利用することができます。プラグインは、pytestの機能を拡張したり、カスタマイズしたりするために使用されます。以下に、代表的なpytestのプラグインについて説明します。
-
pytest-cov
pytest-covは、コードのカバレッジを測定するためのプラグインです。pytestでテストを実行する際に、カバレッジ情報を取得してくれます。HTML形式のレポートを出力することができるため、コードのカバレッジを視覚的に確認することができます。 -
pytest-html
pytest-htmlは、テスト結果をHTML形式で出力するためのプラグインです。HTML形式で出力することで、テスト結果を視覚的に確認することができます。また、レポートにはスクリーンショットやログなどの情報も含めることができます。 -
pytest-xdist
pytest-xdistは、複数のプロセスやマシンでテストを並列実行するためのプラグインです。これにより、テストの実行時間を短縮することができます。 -
pytest-flake8
pytest-flake8は、コードの品質を検証するためのプラグインです。flake8という静的解析ツールを利用して、コードに問題がないかをチェックします。pytestでテストを実行する際に、flake8の結果も一緒に表示することができます。 -
pytest-django
pytest-djangoは、Djangoフレームワークでのテストをサポートするためのプラグインです。Djangoのモデルやビューなどをpytestでテストすることができます。 -
pytest-selenium
pytest-seleniumは、Selenium WebDriverを利用してWebアプリケーションのテストを実行するためのプラグインです。ブラウザを自動操作して、Webアプリケーションの挙動をテストすることができます。また、スクリーンショットを取得することもできます。 -
pytest-mock
pytest-mockは、モックを利用してテストを実行するためのプラグインです。unittest.mockという標準ライブラリを利用して、モックオブジェクトを生成してテストすることができます。
プラグインの使い方
pytestのプラグインは、pipコマンドを使用してインストールすることができます。具体的には、次のようなコマンドを実行します。
$ pip install pytest-cov
これで、pytest-cov
プラグインがインストールされます。pytest-cov
プラグインを使用する場合は、pytestのコマンドライン引数として、--cov
オプションを指定します。--cov
オプションの後には、カバレッジを測定する対象のパッケージやモジュールを指定します。例えば、次のようになります。
$ pytest --cov=myapp tests/
これで、myapp
パッケージ次のコードのカバレッジを測定することができます。カバレッジ情報は、ターミナルに出力されます。また、HTML形式のレポートを生成する場合は、--cov-report
オプションを指定します。例えば、次のようになります。
$ pytest --cov=myapp --cov-report=html tests/
これで、カバレッジ情報をHTML形式で出力することができます。
pytest-html
プラグインを使用する場合も、同様にpipコマンドでインストールします。
$ pip install pytest-html
テスト結果をHTML形式で出力するには、--html
オプションを指定します。例えば、次のようになります。
$ pytest --html=report.html tests/
これで、report.html
というファイルにテスト結果がHTML形式で出力されます。また、pytest-html
プラグインは、--self-contained-html
オプションを指定することで、HTMLファイルに必要なリソースを1つのファイルにまとめることもできます。例えば、次のようになります。
$ pytest --html=report.html --self-contained-html tests/
これで、report.html
というファイルに必要なリソースが1つのファイルにまとめられて出力されます。
他のプラグインについても、インストール方法と使い方はそれぞれ異なりますが、pytestのコマンドライン引数にオプションを指定することで利用できるようになります。
テストのカバレッジの測定
pytest-cov
プラグインを使用することで、テストのカバレッジを測定することができます。以下は、pytest-cov
プラグインを使用したテストの例です。
$ pytest --cov=my_module tests/
この例では、--cov
オプションを使用して、my_module
という名前のモジュールのカバレッジを測定しています。pytest-cov
プラグインは、テストを実行し、モジュールのカバレッジを計算し、レポートを生成します。
テストのスキップ
テストが実行できない場合、スキップすることができます。例えば、次のようにして、特定の条件でテストをスキップすることができます。
import pytest
def test_division():
divisor = 0
dividend = 10
if divisor == 0:
pytest.skip("Can't divide by zero")
assert dividend / divisor == 5
この例では、divisor
が0
の場合、pytest.skip()
関数によってテストがスキップされます。
参考