概要
Pythonのunittest
モジュールとparameterized
ライブラリを使用すると、さまざまな組み合わせのテストを簡潔に記述できることがわかったので紹介します。似たようなテストをしたい場合は、ダラダラとテストケースを羅列するとなかなか面倒であり、また保守性も低いです。そんな時にparameterized
ライブラリは使いやすいと思います。
サンプルコード
import unittest
from parameterized import parameterized
class TestFruits(unittest.TestCase):
FRUIT_COLORS = {
"apple": "red",
"banana": "yellow",
"grape": "purple",
}
@parameterized.expand([
("apple", "red"),
("banana", "yellow"),
("grape", "purple"),
])
def test_fruit_color(self, fruit, expected_color):
self.assertEqual(self.FRUIT_COLORS[fruit], expected_color)
上記test_fruit_color
テストケースでは、各フルーツの色が期待される色と一致することを確認しています。(FRUIT_COLORS
辞書から取得したフルーツの色と、テストケースのパラメータとして提供された色を比較)
apple
の場合はred
であるかどうか、といった形です。
parameterized.expand
デコレータを使用することで、テストケースを各フルーツと色の組み合わせに対して実行できるのです。
test_fruit_color(self, fruit, expected_color)
では、fruit
にはparameterized.expand
デコレータによって提供されるパラメータである"apple"、"banana"、"grape"
が入り、expected_color
の方には、"red"、"yellow"、"purple"
が渡されます。
ちなみに上記では引数は二つでしたが、一つや三つでも可能です。
import unittest
from parameterized import parameterized
class TestFruits(unittest.TestCase):
FRUIT_COLORS = {
"apple": "red",
"banana": "yellow",
"grape": "purple",
}
FRUIT_PRICES = {
"apple": 100,
"banana": 50,
"grape": 200,
}
# 引数一つの場合(辞書に含まれているかどうかの確認)
@parameterized.expand([
("apple",),
("banana",),
("grape",),
])
def test_fruit_exists(self, fruit):
self.assertIn(fruit, self.FRUIT_COLORS)
# 引数二つの場合(組み合わせが正しいかどうかの確認)
@parameterized.expand([
("apple", "red"),
("banana", "yellow"),
("grape", "purple"),
])
def test_fruit_color(self, fruit, expected_color):
self.assertEqual(self.FRUIT_COLORS[fruit], expected_color)
# 引数三つの場合(組み合わせが正しいかどうかの確認)
@parameterized.expand([
("apple", "red", 100),
("banana", "yellow", 50),
("grape", "purple", 200),
])
def test_fruit_color_and_price(self, fruit, expected_color, expected_price):
self.assertEqual(self.FRUIT_COLORS[fruit], expected_color)
self.assertEqual(self.FRUIT_PRICES[fruit], expected_price)
if __name__ == '__main__':
unittest.main()
@parameterized.expand
に渡すリストの各要素と、テストメソッドの引数の数と一致していない場合は失敗します。順序も同じになります。
ただし、test_fruit_color
メソッドは2つの引数を期待しているにも関わらず、@parameterized.expand
デコレータで提供されているテストケースは1つの引数しか提供していない場合、このテストケースは「スキップ」されます。失敗するわけではないので要注意です。
test_fruit_color
メソッドの引数の方が少ない場合はTypeError
なります。
ここでの例では、@parameterized.expand
のリスト内に直接データを記述していますが、実際に運用する場合は、別の関数の結果を渡してあげたり、DBからデータを取得して渡してあげたりすると管理しやすいかと思います。