新規プロジェクトのテスト基盤を選ぶとき、「標準ライブラリの unittest のままでよいのか、それとも pytest に移行すべきか」で手が止まってしまうことはないでしょうか。unittest でテストを書き続けるうちに、TestCase の継承や self.assertEqual() といった専用メソッドが増え、セットアップ処理の重複でテストコードが膨らんでいく、という悩みはよく聞かれます。
一方で、pytest を採用すると決めても、「fixture や parametrize は結局何が嬉しいのか」「既存の unittest 資産はどうなるのか」「そもそもメンテナンスは続いているのか」といった疑問が次々に出てきて、採用判断に踏み切れないこともあります。情報が断片的だと、ツールの良し悪しよりも「自分のプロジェクトに合うか」が見えにくいものです。
pytest は、こうした「素のテストは簡単に書きたいが、規模が大きくなっても破綻させたくない」というニーズに応えるために設計された Python のテストフレームワークです。素の assert 文でテストが書け、fixture による準備処理の再利用、parametrize による入力違いのテストの集約、豊富なプラグインによる拡張といった仕組みを備えています。
本記事では、pytest の基本的な使い方を、インストールと最小のテストから fixture・parametrize・プラグインまで順を追って解説します。あわせて unittest や nose2 との違い、採用判断のポイント、メンテナンス状況も整理し、「自プロジェクトに pytest を採用すべきか」を判断するための材料を提供します。なお本記事は公式ドキュメントと README をもとに構成しており、特定のコードを筆者が実行・検証したものではありません。コード例はすべて公式のものを引用しています。
pytestとは|Pythonテストを簡潔に書けるOSS
pytest は、Python 向けのテストフレームワークです。公式の説明では「小さなテストを簡単に書け、かつアプリケーションやライブラリの複雑な機能テストまでスケールする」フレームワークと位置づけられています(pytest README)。つまり、最初のうちは数行の関数でテストを書き始められ、プロジェクトが大きくなっても同じ仕組みのまま拡張していけることを狙ったツールです。
採用を検討するうえで最初に押さえておきたい基本情報を、リポジトリのメタデータから整理します。
項目 | 値 |
|---|---|
リポジトリ | pytest-dev/pytest |
主要言語 | Python |
ライセンス | MIT |
スター数 | 14,235 |
Fork 数 | 3,198 |
最終更新(push) | 2026-06-19 |
対応バージョン | Python 3.10 以降、または PyPy3 |
公開状態 | 公開リポジトリ(アーカイブ・フォークではない) |
このリポジトリはアーカイブされておらず、フォークでもない本家のアクティブなプロジェクトです(archived = false / fork = false)。ライセンスは MIT で、商用・非商用を問わず比較的自由に利用できる点も、業務での採用検討において扱いやすい条件です。
pytest がもたらす最大の価値は、テストの記述をシンプルに保てることにあります。unittest のようにクラスを継承して専用の assert メソッドを呼び出す必要がなく、Python の素の assert 文をそのまま書けます。それでいて、テストの自動探索、fixture による準備処理の共通化、1,300 を超える外部プラグインによる拡張といった、大規模化に耐える機能を備えています。
より詳しい仕様や使い方は、公式ドキュメント(docs.pytest.org)とGitHub リポジトリで確認できます。本記事でも要所で公式ドキュメントの該当ページを案内していきます。
pytestの基本|素のassertで書ける最小のテスト
まずは pytest の使い方の出発点である、インストールと最小のテストから見ていきます。
インストールと最初のテスト
pytest は pip でインストールできます。公式の Getting Started では、次のコマンドが案内されています。
pip install -U pytest
テストファイルは、デフォルトではカレントディレクトリ以下の test_*.py または *_test.py という命名のファイルが自動的に探索・実行されます。クラスの継承や明示的な登録は必要なく、命名規則に沿ってファイルと関数を置くだけです。
README で示されている最小のテスト例は次のとおりです。
# content of test_sample.py
def inc(x):
return x + 1
def test_answer():
assert inc(3) == 5
出典: pytest README
このファイルを置いて pytest コマンドを実行すると、test_answer が収集・実行されます。クラスを定義することも、専用の assert メソッドを呼ぶこともなく、Python の素の assert 文だけでテストが完結している点に注目してください。
assertion introspection の何が嬉しいか
pytest の大きな特徴のひとつが、assertion introspection(アサーションの詳細解析)と呼ばれる仕組みです。素の assert 文を書くだけで、テストが失敗したときに、評価された実際の値まで含めた詳細な情報が表示されます。
先ほどの例を実行して失敗した場合、README では次のような出力が示されています。
============================= test session starts =============================
collected 1 items
test_sample.py F
================================== FAILURES ===================================
_________________________________ test_answer _________________________________
def test_answer():
> assert inc(3) == 5
E assert 4 == 5
E + where 4 = inc(3)
test_sample.py:5: AssertionError
========================== 1 failed in 0.04 seconds ===========================
出典: pytest README
注目すべきは assert 4 == 5 と where 4 = inc(3) の行です。単に「テストが失敗した」と表示するのではなく、inc(3) が実際には 4 を返していて、期待した 5 と一致しなかったことまで読み取れます。
unittest では、同じ比較を行うために self.assertEqual(inc(3), 5) のように専用メソッドを使い分ける必要がありました。「等しいか」「含まれるか」「真か」などに応じて assertEqual / assertIn / assertTrue といった API を覚えるコストがかかります。pytest では素の assert 文を書くだけで、失敗時に同等以上の情報が得られるため、覚えるべき API が大きく減ります。これが、unittest からの移行を検討するエンジニアにとって最初に実感しやすいメリットです。
assertion introspection の挙動について、より詳しくは公式のassert の how-toで確認できます。
pytestのfixtureとは|依存性注入でテスト準備を再利用する
テストを書き進めると、「このテストの前にデータベース接続を用意したい」「テスト用のオブジェクトを毎回作りたい」といった準備処理が増えてきます。pytest では、この準備処理を fixture という仕組みで再利用します。fixture は、pytest を採用する大きな動機のひとつです。
fixtureの基本と依存性注入
fixture は @pytest.fixture デコレータで定義する、再利用可能なセットアップ部品です。テスト関数は、必要な fixture を「引数として宣言する」ことで要求します。pytest は、テスト関数の引数名と同じ名前の fixture を探し、その戻り値を自動的に渡してくれます。これが依存性注入(dependency injection)と呼ばれる仕組みです。
公式ドキュメントの基本例は次のとおりです。
@pytest.fixture
def fruit_bowl():
return [Fruit("apple"), Fruit("banana")]
def test_fruit_salad(fruit_bowl):
fruit_salad = FruitSalad(*fruit_bowl)
assert all(fruit.cubed for fruit in fruit_salad.fruit)
test_fruit_salad は fruit_bowl という引数を宣言しているだけですが、pytest が同名の fixture を見つけて、その戻り値を自動的に注入します。テスト側は「何を必要とするか」を引数で宣言するだけでよく、準備処理の中身をテスト関数に書く必要がありません。fixture はほかの fixture を要求することもでき、準備処理を小さな部品の連鎖として組み立てられます。
スコープとconftest.pyによる共有
fixture には、どのタイミングで作られて破棄されるかを決める「スコープ」があります。指定できるスコープは function(既定)/ class / module / package / session の 5 種類です。たとえば function スコープではテスト関数ごとに fixture が作り直され、session スコープではテストセッション全体で 1 回だけ作られて使い回されます。データベース接続のように生成コストが高いリソースは広いスコープにすることで、テスト全体の実行時間を抑えられます。
また、fixture を conftest.py というファイルに置くと、import を書かなくても複数のテストモジュール間で共有できます。pytest が conftest.py を自動的に探索するため、共通の準備処理を一箇所にまとめておけば、ディレクトリ配下のテストから横断的に利用できます。
yieldによるティアダウン
テストでは、準備した後始末(ティアダウン)も重要です。作成したユーザーを削除する、開いた接続を閉じる、といった後処理を確実に行いたい場面で、pytest では yield を使った fixture が役立ちます。
@pytest.fixture
def user(admin_client):
user = admin_client.create_user()
yield user
admin_client.delete_user(user)
この fixture では、yield までのコードがテスト前の準備(ユーザー作成)として実行され、yield で生成したオブジェクトがテストに渡されます。そして yield 以降のコード(ユーザー削除)が、テスト終了時に後処理として実行されます。準備と後始末を 1 つの fixture にまとめて書けるため、「作ったら必ず片付ける」処理を見通しよく管理できます。
unittest の setUp / tearDown がクラス単位でメソッドを分けて書くのに対し、pytest の fixture は関数ベースで、必要なテストにだけ引数として注入できます。準備処理の再利用と後始末の確実さをどう扱うかは、テスト基盤を選ぶうえで重要な判断材料です。fixture の詳細は公式のFixtures how-toを参照してください。
pytestのparametrizeとプラグイン|テストを増やさず網羅する
同じロジックを複数の入力で確認したい、あるいは並列実行やカバレッジ計測を後から足したい。こうした「テストを増やさずに網羅性と機能を広げたい」ニーズに応えるのが、parametrize とプラグインの仕組みです。
parametrizeで入力違いのテストをまとめる
@pytest.mark.parametrize を使うと、1 つのテスト関数を複数の入力で繰り返し実行できます。入力と期待値の組み合わせを並べておくだけで、それぞれが独立したテストケースとして収集・実行されます。
公式ドキュメントの例は次のとおりです。
import pytest
@pytest.mark.parametrize("test_input,expected", [("3+5", 8), ("2+4", 6), ("6*9", 42)])
def test_eval(test_input, expected):
assert eval(test_input) == expected
出典: Parametrizing tests — pytest
このデコレータは 3 つの (test_input, expected) の組を定義しており、test_eval がそれぞれの組で順番に 3 回実行されます。同じテストロジックを入力ごとにコピー&ペーストする必要がなく、入力一覧を 1 か所で管理できるため、テストケースの追加・修正が容易になります。
parametrize のデコレータは重ねがけ(stacking)もでき、複数のパラメータ群を組み合わせると、その直積(すべての組み合わせ)がテストケースとして生成されます。境界値や入力パターンを網羅したいときに、テスト関数を増やさずに対応できる点が実務的なメリットです。詳しい使い方はParametrize how-toで確認できます。
なお、parametrize は「手で列挙した入力」でテストを回す仕組みです。これに対して、入力を自動生成して性質を検証したい場合は、pytest と併用できるプロパティベーステストのライブラリ(Hypothesis など)が補完的な選択肢になります。両者は競合ではなく、用途に応じて組み合わせて使えます。
豊富なプラグインで機能を拡張する
pytest のもうひとつの強みが、プラグインによる拡張性です。README では、1,300 を超える外部プラグインを持つ豊富なプラグインアーキテクチャと活発なコミュニティが特徴として挙げられています(pytest README)。
代表的なプラグインには、次のようなものがあります。
- pytest-cov: テストカバレッジを計測する
- pytest-xdist: テストを並列実行して実行時間を短縮する
- pytest-mock: モック(テスト用の代替オブジェクト)を扱いやすくする
- pytest-django: Django プロジェクトのテストを支援する
これらは、最初はシンプルなテストから始めて、後から「カバレッジを測りたい」「並列で回したい」といった要件が出てきたときに、テストの書き方を大きく変えずに追加できます。利用できるプラグインの一覧は、公式のプラグイン一覧で確認できます。採用判断において、「将来の要件に後付けで対応できるか」は重要な観点であり、この拡張性は pytest の大きな決め手のひとつです。
pytestとunittest・nose2の違い|採用の判断軸
ここまで pytest の機能を見てきましたが、採用判断の核心は「類似ツールとどう違うか」です。Python のテストフレームワークとして比較対象になりやすい unittest と nose2 を取り上げ、判断軸を整理します。
観点 | pytest | unittest(標準ライブラリ) | nose2 |
|---|---|---|---|
導入 |
| 標準同梱でインストール不要 |
|
テストの書き方 | 関数ベース・素の |
| unittest スタイルが基本 |
準備処理の再利用 | fixture(依存性注入・スコープ・yield) |
| unittest 相当 |
拡張性 | 1,300+ のプラグイン | 限定的 | プラグイン機構あり |
エコシステム・活発さ | 大規模・活発(de facto standard) | 標準同梱で安定 | pytest に比べ小規模 |
unittest は Python の標準ライブラリに同梱されており、追加インストールなしで使える点が利点です。一方で、TestCase クラスの継承と self.assertEqual() などの専用 assert メソッドが必須で、テストコードが冗長になりがちです。準備処理の再利用も setUp / tearDown に限られ、pytest の fixture のような柔軟な依存性注入はありません。
ここで採用検討のうえで見逃せないのが、pytest は unittest(や trial)形式で書かれたテストスイートをそのまま実行できるという点です。つまり、既存の unittest 資産を捨てずに pytest 上で動かしながら、新しいテストから fixture や parametrize を使う、という段階的な移行ができます。これにより「全部書き直さないと移行できない」というハードルが下がります。unittest からの移行手順は公式のunittest 連携 how-toにまとまっています。
nose2 は、unittest のテストランナーを拡張したフレームワークで、unittest と pytest の中間的な存在です。プラグイン機構や設定ファイルを持ちますが、エコシステムの規模・コミュニティの活発さ・開発の勢いの点で pytest に大きく劣ります。pytest の fixture のような強力な依存性注入の仕組みもありません。実務では pytest が事実上の標準(de facto standard)になっており、nose2 は移行の踏み石的な位置づけと評されることが多いツールです。
判断軸を整理すると、次のように考えられます。
- 追加インストールを避けたい・ごく小規模なスクリプトのテストで足りる → unittest で十分なこともある
- 新規プロジェクトで、テストの記述性・再利用性・拡張性を重視する → pytest が有力
- 既存の unittest 資産があるが段階的に改善したい → 既存テストをそのまま動かせる pytest が移行しやすい
なお、unittest はあくまで標準ライブラリの一部であり、上記の比較は機能特性に基づく一般的な整理です。実際の選定では、チームの習熟度や既存資産の量も考慮することをおすすめします。
pytestの開発状況とまとめ|採用前にチェックすべき点
最後に、採用判断のもうひとつの軸である「メンテナンス状況は健全か」を確認します。OSS を業務に採用する際は、機能だけでなく、開発が継続しているか・コミュニティが活発かを見ておくことが重要です。
pytest のリポジトリ指標は次のとおりです。
- スター数: 14,235
- Fork 数: 3,198
- 最終更新(push): 2026-06-19
- ライセンス: MIT
- 状態: アーカイブ・フォークではない、公開中の本家リポジトリ
14,000 を超えるスターと 3,000 を超える Fork は、広く使われ、改変・貢献の母数が大きいことを示します。最終更新が直近である点からも、開発が止まっていないことが読み取れます。あわせて、1,300 を超えるプラグインを支える活発なコミュニティの存在も、長期的な利用における安心材料です。変更履歴は公式のChangelogで追えるため、採用前にリリース頻度や互換性の方針を確認しておくとよいでしょう。
本記事の内容を、採用判断の観点から整理します。
- pytest は素の
assert文と関数ベースでテストを書けるため、unittest に比べて記述がシンプルで、覚えるべき API が少ない - fixture による依存性注入・スコープ制御・yield ティアダウンで、準備処理と後始末を再利用しやすい
- parametrize で入力違いのテストを集約でき、1,300+ のプラグインで機能を後付けできる
- unittest 形式のテストをそのまま実行できるため、既存資産を活かした段階的な移行が可能
- スター数・Fork 数・最終更新・MIT ライセンス・活発なプラグインコミュニティから、メンテナンスは健全と判断できる
新規プロジェクトでテストの記述性と拡張性を重視する場合や、unittest からの段階的な移行を検討している場合、pytest は有力な選択肢になります。まずは pip install -U pytest と最小のテスト 1 本から始め、必要に応じて fixture・parametrize・プラグインへ広げていく進め方が、無理のない導入になります。実際に書き始める際は、公式のGetting Startedと公式ドキュメントを参照してください。


