0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Python】unittestモジュールとparameterizedライブラリを使用して効率的にテストケースを書く

Posted at

概要

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からデータを取得して渡してあげたりすると管理しやすいかと思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?