Pythonで関数の単体テストを書く(unittest, pytest)
この記事では、Pythonの`unittest`モジュールと`pytest`フレームワークを使った関数の単体テストの書き方について説明します。様々なテストパターンや、テストを効率的に行うためのテクニックを紹介します。
目次
- unittestモジュールによる単体テスト
- テストケースの作成
- setUp()とtearDown()メソッド
- アサーション
- テストの実行
- pytestフレームワークによる単体テスト
- fixtureを使ったテスト
- parametrizeを使ったテスト
- テストの実行とレポート
unittestモジュールによる単体テスト
Python標準ライブラリの`unittest`モジュールは、単体テストを作成するためのフレームワークを提供します。`TestCase`クラスを継承し、テストメソッドを作成することで、関数のテストを行うことができます。
import unittest
def add(x, y):
return x + y
class TestAdd(unittest.TestCase):
def test_add_positive(self):
self.assertEqual(add(2, 3), 5)
def test_add_negative(self):
self.assertEqual(add(-2, 3), 1)
def test_add_zero(self):
self.assertEqual(add(0, 0), 0)
if __name__ == '__main__':
unittest.main()
上記は`add`関数のテストケースです。`assertEqual`メソッドを使って期待値と実際の値を比較しています。`if __name__ == '__main__':` のブロックは、スクリプトを直接実行した際にテストを実行するためのものです。
テストケースの作成
テストケースは、`test_`で始まるメソッド名で定義します。`unittest`は`test_`で始まるメソッドを自動的にテストケースとして認識します。
class TestStringMethods(unittest.TestCase):
def test_upper(self):
self.assertEqual('foo'.upper(), 'FOO')
def test_isupper(self):
self.assertTrue('FOO'.isupper())
self.assertFalse('Foo'.isupper())
def test_split(self):
s = 'hello world'
self.assertEqual(s.split(), ['hello', 'world'])
with self.assertRaises(TypeError):
s.split(2)
複数のテストケースを作成することで、関数の様々な側面をテストできます。`assertRaises`コンテキストマネージャーを使って例外処理もテストできます。
setUp()とtearDown()メソッド
`setUp()`メソッドは各テストケースの前に実行され、テストに必要な環境を準備するために使用します。`tearDown()`メソッドは各テストケースの後で実行され、使用したリソースを解放するために使用します。
import unittest
class TestSetupTeardown(unittest.TestCase):
def setUp(self):
print('Setup')
def tearDown(self):
print('Teardown')
def test_case1(self):
print('Test Case 1')
self.assertTrue(True)
def test_case2(self):
print('Test Case 2')
self.assertTrue(True)
if __name__ == '__main__':
unittest.main()
アサーション
テスト結果の検証には、アサーションメソッドを使用します。`assertEqual`, `assertTrue`, `assertFalse`, `assertRaises`など、様々なアサーションメソッドがあります。
self.assertEqual(a, b) # aとbが等しいことを検証
self.assertTrue(x) # xがTrueであることを検証
self.assertFalse(y) # yがFalseであることを検証
with self.assertRaises(ValueError): # ValueError例外が発生することを検証
some_function()
テストの実行
コマンドラインから`python -m unittest <test_module>.py`を実行することで、テストを実行できます。`test_module.py`はテストケースを含むPythonファイルです。
python -m unittest test_my_module.py
pytestフレームワークによる単体テスト
`pytest`は、`unittest`よりも簡潔で使いやすいテストフレームワークです。`unittest`と同様に、関数のテストを行うことができますが、より少ないコードでテストを作成できます。
import pytest
def add(x, y):
return x + y
def test_add_positive():
assert add(2, 3) == 5
def test_add_negative():
assert add(-2, 3) == 1
def test_add_zero():
assert add(0, 0) == 0
pytestでは、`assert`文を使って期待値と実際の値を比較します。テスト関数の名前は`test_`で始める必要があります。
fixtureを使ったテスト
fixtureは、テストに必要な環境を準備するための関数です。`@pytest.fixture`デコレータを使ってfixtureを定義します。
import pytest
@pytest.fixture
def data():
return [1, 2, 3]
def test_data(data):
assert sum(data) == 6
parametrizeを使ったテスト
`@pytest.mark.parametrize`デコレータを使うことで、複数のテストケースを簡単に作成できます。
import pytest
@pytest.mark.parametrize('x, y, expected',
[(2, 3, 5), (-2, 3, 1), (0, 0, 0)])
def test_add(x, y, expected):
assert add(x, y) == expected
テストの実行とレポート
コマンドラインから`pytest`を実行することで、テストを実行し、結果をレポートとして出力します。`-v`オプションを付けることで、より詳細なレポートを得ることができます。
pytest
pytest -v