【Python】unittestモジュールで単体テストを実行する

スポンサーリンク

最近、他の言語で単体テスト自動化するために色々調べてみて単体テストツールについて興味を持つようになりました。

そこで今勉強しているPythonの単体テスト事情について調べてみたところ、Pythonでの単体テストフレームワークの主流は、unittestpytestが良く使われているみたいです。

今回はその中でもPythonの標準ライブラリとして提供されているunittestがどんなものか試してみました。

unittestモジュール

基本構文

unittestモジュールは、Pythonの標準ライブラリとして提供されている単体テスト用のモジュールです。以下の構文にもある通りPythonに最初から同梱されているモジュールなのでimportすれば使えるようになります。

import unittest

class Testクラス(unittest.TestCase):
    def test_メソッド(self):
        self.assertEqual(期待値、検査値)

unittest.TestCaseクラスを継承した単体テストクラスを作成し、単体テストのメソッドを作成していきます。

よく使用するテストメソッド

unittestでよく使う代表的なメソッドは以下の通りです。
テスト結果が想定と違っていた場合はAssertionErrorが発生します。

メソッドテスト内容
assertEqual(a,b)aとbが等しければOK
assertNotEqual(a,b)aとbが等しくなければOK
assertTrue(x)xがTrueならOK
assertFalse(x)xがFalseならOK
assertIs(a,b)aとbが同じオブジェクトであればOK
assertIsNot(a,b)aとbが同じオブジェクトでなければOK
assertIsNone(x)xがNoneであればOK
assertIsNotNone(x)xがNoneでなければOK
assertIn(a,b)aがbに含まれていればOK
assertNotIn(a,b)aがbに含まれていなければOK
assertIsInstance(a,b)aがbのインスタンスであればOK
assertNotIsInstance(a,b)aがbのインスタンスでなければOK
よく使うテストメソッド

単体テスト実行コマンド

単体テストを実装して実行するときは以下のコマンドを実行します。

python -m unittest test_テスト対象モジュール.py

-mはモジュールを実行する意味でここではunittestモジュールを実行するという意味です。

 
テストモジュールは、ディスカバリというtest_*.pyというファイルを検索して自動で実行してくれ  る機能があるので必ずtest_という名前で作成するようにしましょう。

unittestを実装してみる

テストされる側のプログラム

実際にunittestを実装してみます。今回はunittestでテストされる側のモジュールとしてcalculation.pyというファイルを作成して以下の関数をサンプルとして作成してみました。

  • 二つの値を足し算する関数(addtion_num)
  • 二つの値を掛け算する関数(multiplication_num)
  • 正の整数を判定する関数(ispositive_int)
#テストされる側のプログラム
#二つの値を足し算
def addtion_num(num1,num2):
    return num1 + num2
#二つの値を掛け算
def multiplication_num(num1,num2):
    return num1 * num2
#正の整数判定
def ispositive_int(num):
    return num > 0

テストプログラム

上記3つの関数をテストするプログラムは以下の通りです。

import unittest
import calculation

class TestCalcFuncs(unittest.TestCase):
    """
    addtion_numの単体テスト(足し算)
    """
    def test_addtion_num(self):
        self.assertEqual(5,calculation.addtion_num(2,3))
        
    """
    multiplication_numの単体テスト(掛け算)
    """
    def test_multiplication_num(self):
        self.assertEqual(6,calculation.multiplication_num(2,3))

    """
    ispositive_intの単体テスト(正の整数判定)
    """  
    def test_ispositive_int(self):
        self.assertTrue(calculation.ispositive_int(2))
        self.assertFalse(calculation.ispositive_int(-1))
        self.assertFalse(calculation.ispositive_int(0))
  • ファイル名は、test_形式にする。
  • 関数名もtest_形式にする。
  • import unittestでunittestモジュールをインポートする。
  • import calculationでテストされる側のモジュールをインポートする。

単体テストの実行

単体テストの実行は、ターミナルなどでunittestモジュールを-mオプションで指定して引数にテストモジュールを指定します。今回のファイル構成では以下のようになります。

python -m unittest test_calculation.py

上述にもある通り、Pythonのunittestはディスカバリという仕組みがあるのでpython -m unittestだけでもテストプログラムが実行されます。

すべてのテストがOKだったときの実行結果です。

(実行結果)
----------------------------------------------------------------------
Ran 3 tests in 0.001s

OK

試しに掛け算のプログラムの期待値をわざと違うものにして実行すると以下のようになります。
(掛け算プログラムの期待値を本来の6→5に変更して実行)

(実行結果)
FAIL: test_multiplication_num (test_calculation.TestCalcFuncs)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\python\py\test_calculation.py", line 15, in test_multiplication_num
    self.assertEqual(5,calculation.multiplication_num(2,3))
AssertionError: 5 != 6

----------------------------------------------------------------------
Ran 3 tests in 0.002s

FAILED (failures=1)

AssertionErrorが発生して期待値は5なのに検査値が6で一致していない旨のエラーが出ています。

こんな感じで単体テストを実装しておくと、想定していた処理結果が違うとエラーになるので不具合などがすぐにわかって品質向上が見込めます。

まとめ

  • unittestはPythonの標準ライブラリなのでimportだけで使える
  • テストされる側のモジュールもテストプログラム内にimportする
  • unittestはほとんどの場合assert(アサーション)メソッドを使う
  • ファイル名や関数名はtest_形式のネーミングルールで実装する
  • ユニットテストを実装することで品質向上が見込める

今回はPython標準のunittestについてでしたが、pythonには他にもpytestという単体テストフレームワークが存在します。pytestも評判がいいみたいなので機会があれば試してみたいと思います。

コメント

タイトルとURLをコピーしました