こんにちは、かつコーチです。
Pythonでテストを書こうとすると、必ず出てくる疑問があります。
「標準ライブラリのunittestと、外部ライブラリのpytest、どっちを使えばいいの?」
ネット上のサンプルコードでも、両方の書き方が混在していて迷いやすいポイントです。
この記事では、unittestとpytestの構文の違いを比較しながら、どちらを選ぶべきかの判断軸を解説します。
読み終える頃には、自分のプロジェクトに合ったテストツールを選べるようになります。
unittestとpytestとは?
unittestとは
unittestは、Pythonに標準で組み込まれているテストフレームワークです。
追加インストール不要で、import unittestとするだけですぐに使えます。
クラスベースでテストを書き、専用のメソッド(assertEqualなど)を使って検証します。
pytestとは
pytestは、外部ライブラリとして提供されているテストフレームワークです。
pip install pytestのインストールが必要ですが、標準のassert文だけでテストが書け、記述量が少なく済みます。
構文比較:同じテストを両方で書いてみる
手順1:テスト対象の関数
税込価格を計算する、同じ関数を対象にします。
# calc.py
def add_tax(price, tax_rate=0.1):
if price < 0:
raise ValueError("価格は0以上である必要があります")
return int(price * (1 + tax_rate))
手順2:unittestで書く場合
unittestでは、TestCaseを継承したクラスの中にテストメソッドを定義します。
# test_calc_unittest.py
import unittest
from calc import add_tax
class TestAddTax(unittest.TestCase):
def test_normal(self):
self.assertEqual(add_tax(1000), 1100)
def test_negative_price(self):
with self.assertRaises(ValueError):
add_tax(-100)
if __name__ == "__main__":
unittest.main()
実行はpython -m unittestで行います。
python -m unittest test_calc_unittest.py
..
----------------------------------------------------------------------
Ran 2 tests in 0.00s
OK
手順3:pytestで書く場合
同じ内容をpytestで書くと、クラスもメソッド名の縛りも不要になります。
# test_calc_pytest.py
import pytest
from calc import add_tax
def test_normal():
assert add_tax(1000) == 1100
def test_negative_price():
with pytest.raises(ValueError):
add_tax(-100)
pytest test_calc_pytest.py
.. [100%]
2 passed in 0.01s
構文比較表
| 観点 | unittest | pytest |
|---|---|---|
| インストール | 不要(標準ライブラリ) | pip install pytestが必要 |
| テストの単位 | TestCaseを継承したクラス | 関数だけでOK |
| 値の比較 | self.assertEqual(a, b) | assert a == b |
| 例外の検証 | self.assertRaises(...) | pytest.raises(...) |
| 実行コマンド | python -m unittest | pytest |
| 記述量 | やや多い | 少ない |
どちらを選ぶべきかの判断軸
判断軸1:外部ライブラリを追加できるか
社内規定やセキュリティポリシーで、外部ライブラリの追加が制限されている現場もあります。
そうした環境では、標準ライブラリだけで完結するunittestが確実な選択肢になります。
判断軸2:記述量とチームの学習コスト
個人開発や、新規にテスト文化を導入する場合はpytestがおすすめです。
assert文だけで書けるため、初めてテストを書くメンバーにも説明しやすい構文です。
判断軸3:既存プロジェクトとの整合性
すでにunittestベースのテストが大量にある場合、無理にpytestへ書き換える必要はありません。
実は、pytestのコマンドはunittest形式のテストコードもそのまま実行できます。
既存のunittestテストを残しつつ、新規テストだけpytestスタイルで書く、という併用も可能です。
よくあるつまずきポイント・エラー対処
unittest形式のクラスをpytestで実行しようとして混乱する
筆者が実際に経験したのが、unittest.TestCaseを継承したクラスに、pytest.raisesを混ぜて書いてしまったケースです。
❌ Before(混在させて動かない書き方)
import unittest
import pytest
from calc import add_tax
class TestAddTax(unittest.TestCase):
def test_negative_price(self):
pytest.raises(ValueError, add_tax(-100))
実行すると、次のエラーメッセージが表示されます。
ValueError: 価格は0以上である必要があります
pytest.raisesはwithブロックの中で使う前提の構文です。
add_tax(-100)を先に評価してしまっているため、例外の捕捉より先にエラーが発生していました。
✅ After(unittest形式に揃えた書き方)
import unittest
from calc import add_tax
class TestAddTax(unittest.TestCase):
def test_negative_price(self):
with self.assertRaises(ValueError):
add_tax(-100)
unittest.TestCaseを使うクラスの中では、self.assertRaisesに統一するのが安全です。
「クラスはunittest、検証だけpytest」のような混在は、思わぬ実行順序のバグを招きやすいので避けましょう。
まとめ
この記事のポイント
unittestは標準ライブラリ、pytestは外部ライブラリで記述量が少ないunittestはクラスベース、pytestは関数ベースで書ける- 外部ライブラリ制限がある現場は
unittest、新規導入はpytestが選びやすい pytestコマンドはunittest形式のテストも実行できるため併用も可能- クラス内で
unittestとpytestの検証構文を混在させるとバグの元になる
次に読むべき記事
- pytestの基本:テストの書き方入門
- モックを使ったテストの書き方(unittest.mock)
- テストカバレッジを計測する方法(pytest-cov)
タグ: Python, 中級者向け, テスト