6
8

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 3 years have passed since last update.

unittest、doctest、noseライブラリについて

Last updated at Posted at 2020-03-07

Pythonのテストについて

Pythonのテストフレームワークである
unittestdoctestnose ライブラリについてまとめます。

unittestによるテスト

標準ライブラリには2つテストフレームがあり、 unittest ライブラリはその1つです。

以下に、 unittest を使用したサンプルコードを記述します。
cap.py にテスト対象のメソッドを記述し、
test_cap.py でテストを実行します。

cap.py
def convert_to_title_case(text):
    # 文字列内の単語の先頭をすべて大文字にする
    return text.title()
test_cap.py

import unittest
import cap

class TestCap(unittest.TestCase):

    def setUp(self):
        print('setUp()メソッドが呼び出されました')

    def tearDown(self):
        print('tearDown()メソッドが呼び出されました')

    def test_one_word(self):
        text = 'python'
        result = cap.convert_to_title_case(text)
        self.assertEqual(result, 'Python')

    def test_multiple_word(self):
        text = 'python programming'
        result = cap.convert_to_title_case(text)
        self.assertEqual(result, 'Python Programming')

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


$ python learn-test/test_cap.py
setUp()メソッドが呼び出されました
tearDown()メソッドが呼び出されました
.setUp()メソッドが呼び出されました
tearDown()メソッドが呼び出されました
.
----------------------------------------------------------------------
Ran 2 tests in 0.003s

OK

setUp()メソッドとtearDown()メソッドについて

setUp()tearDown() の目的は、
テストが必要とする外部リソースを確保・解放することです。
ここでの外部リソースは、例えばデータベース接続や、なんらかのテストデータのことで、
テストを実行する前後になんらかの処理を行いたい場合に有用です。

しかし、 unittestライブライリの setUp()tearDown() はクラス単位で作成するものの、テストごとに実行されます。

ちなみに、Python3.2以降では、setUpClassやtearDownClass、setUpModuleやtesrDownModuleが追加され、
これらを使用すれば、クラスやモジュールレベルで実行できるようになります。

doctestによるテスト

標準ライブラリに含まれている doctest パッケージを使用すれば、
docstring(クラスや関数内に記述するコメント)の中にテストを書くことができます。

以下、テストが失敗する場合と成功場合のコードを書いて挙動を確認します。

テストが失敗する場合

test_faile_cap_with_docstring.py

def convert_to_title_case(text):

    '''
    >>> convert_to_title_case('python')

    'Python'

    >>> convert_to_title_case('Python Programming')
    Error

    '''
    return text.title()

if __name__ == "__main__":

    import doctest
    doctest.testmod()

$ python test_cap_with_docstring.py
**********************************************************************
File "test_cap_with_docstring.py", line 5, in __main__.convert_to_title_case
Failed example:
    convert_to_title_case('Python Programming')
Expected:
    Error
Got:
    'Python Programming'
**********************************************************************
1 items had failures:
   1 of   2 in __main__.convert_to_title_case
***Test Failed*** 1 failures.

テストが成功する場合

test_success_cap_with_docstring.py

def convert_to_title_case(text):

    '''
    >>> convert_to_title_case('python')

    'Python'

    >>> convert_to_title_case('python programming')

    'Python Programming'

    '''
    return text.title()

if __name__ == "__main__":

    import doctest
    doctest.testmod()

$ python test_success_cap_with_docstring.py
$

すべてのテストが成功した場合は、何も表示されません。
詳細を確認する場合は -v オプションをつけると確認できます。

$python test_success_cap_with_docstring.py -v
Trying:

    convert_to_title_case('python')

Expecting:

    'Python'

ok
Trying:

    convert_to_title_case('python programming')

Expecting:

    'Python Programming'

ok
1 items had no tests:

    __main__

1 items passed all tests:
   2 tests in __main__.convert_to_title_case
2 tests in 2 items.
2 passed and 0 failed.
Test passed.

nose ライブライリ使用したテスト

nose はPythonのサードパーティーのテストフレームワークの1つです。

まずはインストールします。

$ pip install nose

nose で使用するメソッドを一部紹介して、サンプルコードを記述します。
メソッドのリファレンスはこちら

  • nose.tools.ok_(expr, msg=None) : expr がTrueかどうか評価します。
  • nose.tools.wq_(a, b,, msg=None) : ab が等価( == )であるか評価します。
  • nose.tools.times(limit) :メソッドにデコレータとして付与し、 limit で指定した時間内にテストが実行されるかどうか評価します。
  • nose.tools.with_setup(setup=None, teardown=None) :デコレータとして、 メソッドレベルsetupteardown の仕組みを実行します。
nose_test_sample.py
import cap
from nose.tools import eq_, with_setup

def setUp():

    print('setUp()メソッドが呼び出されました')

def tearDown():

    print('tearDown()メソッドが呼び出されました')

def set_ok():

    print('set_ok()メソッドが呼びだれました。')

@with_setup(set_ok)
def test_one_work():

    text = 'python'
    result = cap.convert_to_title_case(text)
    eq_(result, 'Python')

def test_multiple_word():

    text = 'python programming'
    result = cap.convert_to_title_case(text)
    eq_(result, 'Python Programming')

nose をインストールすると、 nosetests コマンドが使用できるようになります

$ nosetests -s -v nose_test_sample.py

setUp()メソッドが呼び出されました
nose_test_sample.test_one_work ... setUp()メソッドが呼び出されました
tearDown()メソッドが呼び出されました
ok
nose_test_sample.test_multiple_word ... ok
tearDown()メソッドが呼び出されました

----------------------------------------------------------------------
Ran 2 tests in 0.024s

OK

setup()teardown() によってモジュールレベルsetUp / tearDown の仕組みを適用します。
ちなみに、パッケージレベルになると、 __init__.py モジュールの中に setUp / tearDown 関数に書く必要があります。

unittestnose のそれぞれの特徴

最後に unittestnose の特徴を列挙します。

unitest

  • PEP8に従っていない
  • JUnitに似せられた
  • TestCase を必ず継承しないといけない。
  • setUp/tearDownの仕組むがクラス単位に縛られるのにも関わらず、メソッドごとに実行

nose

  • 継承が不要等、簡単にテストが書ける
  • プラグインが豊富
  • PEP8に従っている
6
8
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
6
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?