python unittestメモを簡単に使う

4916 ワード

最近、プロジェクトをテストしてプロジェクトコードの変更が以前の機能に影響を与えることを防止するために使用されているので、pythonのunittestについて初歩的に理解しました.以下は簡単なメモです.
主にunittest公式ドキュメントを参照
pythonはテストに使用する多くのツールを提供しています.unittestは最も一般的な1つです.以下はunittestが使用する簡単な例です.
import unittest

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'])
        # check that s.split fails when the separator is not a string
        with self.assertRaises(TypeError):
            s.split(2)

if __name__ == '__main__':
    unittest.main()

ここで、TestCaseクラスを継承するサブクラスを設定します.このクラスでは、3つの異なるテスト方法が定義されています.名前はtestで始まる.これにより,後でテスト用例を判断する際にこれらの方法をtest suiteに組み込むことができる.
このうち,ブール型が一致しているかどうかを判断するassertTrueやassertFalseのほかに,raiseが一度であるかどうかを判断するassertRaisesがある.このようなassertメソッドを使用して、より多くのテストを行うことができます.mainを実行すると、これらのテスト例が順次実行されます.実行順序は、これらのメソッドの文字列アルファベット順に実行されます.
コードを見てみましょう.
import unittest

class DefaultWidgetSizeTestCase(unittest.TestCase):
    def test_default_widget_size(self):
        widget = Widget('The widget')
        self.assertEqual(widget.size(), (50, 50))

このコードでは、まずwidgetを初期化し、それに対応するテストを行う欠点があります.いくつかの異なるテスト例があれば、毎回初期化しなければなりません.ここで、unittestはsetUpメソッドを使用して、以下のように統一的な初期化環境を提供します.
import unittest

class WidgetTestCase(unittest.TestCase):
    def setUp(self):
        self.widget = Widget('The widget')

    def test_default_widget_size(self):
        self.assertEqual(self.widget.size(), (50,50),
                         'incorrect default size')

    def test_widget_resize(self):
        self.widget.resize(100,150)
        self.assertEqual(self.widget.size(), (100,150),
                         'wrong size after resize')

ここでseturpで必要な環境を初期化し、他のテスト方法をそのままその環境で実行すればよい.テストの時、プログラムはまずsetUpによって環境を初期化してからテストを行います.setUp自身がraiseで異常が発生した場合、テスト全体がエラーを報告し、テスト方法は実行されません.
同様に、テストが完了すると、tearDownメソッドを使用して、環境を最初の状態に戻す必要がある場合があります.
import unittest

class WidgetTestCase(unittest.TestCase):
    def setUp(self):
        self.widget = Widget('The widget')

    def tearDown(self):
        self.widget.dispose()

この作業環境の作成と破棄はfixtureとなる.
テスト例はtest suiteによって組み合わされ、多くの場合unittestが呼び出される.mian()は、携帯電話のすべてのモジュールのテスト例を実行し、実行します.
また、test suiteを独自に構築することもできます.
def suite():
    suite = unittest.TestSuite()
    suite.addTest(WidgetTestCase('test_default_widget_size'))
    suite.addTest(WidgetTestCase('test_widget_resize'))
    return suite

if __name__ == '__main__':
    runner = unittest.TextTestRunner()
    runner.run(suite())

ここではTestSuiteを定義し、testで始まるいくつかのテスト方法をテスト例としてsuiteにインスタンス化します.最後にテストのTextTestRunnerを構築し、そのrunnerで対応するsuiteを実行すればよい.
上記のすべての例では、各テストの間に1回のテストが実行され、ループ反復テストは行われません.ループテストが必要な場合はsubTestという方法を使用します.
class NumbersTest(unittest.TestCase):

    def test_even(self):
        """
        Test that numbers between 0 and 5 are all even.
        """
        for i in range(0, 6):
            with self.subTest(i=i):
                self.assertEqual(i % 2, 0)

これにより、テスト後の出力は次のようになります.
======================================================================
FAIL: test_even (__main__.NumbersTest) (i=1)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "subtests.py", line 32, in test_even
    self.assertEqual(i % 2, 0)
AssertionError: 1 != 0

======================================================================
FAIL: test_even (__main__.NumbersTest) (i=3)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "subtests.py", line 32, in test_even
    self.assertEqual(i % 2, 0)
AssertionError: 1 != 0

======================================================================
FAIL: test_even (__main__.NumbersTest) (i=5)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "subtests.py", line 32, in test_even
    self.assertEqual(i % 2, 0)
AssertionError: 1 != 0

subTestがループ内assertEqualを直接使用しない場合、プログラムは最初のテストエラーに遭遇したときにテストを終了します.またiの値も表示できません.
======================================================================
FAIL: test_even (__main__.NumbersTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "subtests.py", line 32, in test_even
    self.assertEqual(i % 2, 0)
AssertionError: 1 != 0
以上が主なunittestの使い方です.