nose

unittestフレームワークnose。pythonは標準でxUnitとdoctestを装備してたんで使ってみましたが、noseは使ったことなかったので試してみました。
まずはinstall

$ easy_install nose

テストコード test_hoge.py

### test_hoge.py

def test_hoge():
  assert False

def test_bar():
  assert True

def baz():
  assert False

class test_class:
  g_counter=0
  
  def __init__(self):
    test_class.g_counter+=1
    self.counter = 0

  def test_one(self):
    self.counter += 1
    print 'self.counter', self.counter
    print 'test_class.g_counter', test_class.g_counter
    assert True

  def test_two(self):
    self.counter += 1
    print 'self.counter', self.counter
    print 'test_class.g_counter', test_class.g_counter
    assert False

  def test_three(self):
    self.counter += 1
    print 'self.counter', self.counter
    print 'test_class.g_counter', test_class.g_counter
    assert False

  def test_four(self):
    self.counter += 1
    print 'self.counter', self.counter
    print 'test_class.g_counter', test_class.g_counter
    assert False

  def test_five(self):
    self.counter += 1
    print 'self.counter', self.counter
    print 'test_class.g_counter', test_class.g_counter
    assert False

いざテスト!

$ nosetests -w .

オプションはカレントディレクトリのスクリプトすべてに対してテストを実行。
んで結果。

FF.FFF.
======================================================================
FAIL: test_hoge.test_class.test_five
----------------------------------------------------------------------
Traceback (most recent call last):
  File "f:\Python26\lib\site-packages\nose-0.11.1-py2.6.egg\nose\case.py", line 183, in runTest
    self.test(*self.arg)
  File "f:\work\nose\test_hoge.py", line 47, in test_five
    assert False
AssertionError: 
-------------------- >> begin captured stdout << ---------------------
self.counter 1
test_class.g_counter 5

--------------------- >> end captured stdout << ----------------------

======================================================================
FAIL: test_hoge.test_class.test_four
----------------------------------------------------------------------
Traceback (most recent call last):
  File "f:\Python26\lib\site-packages\nose-0.11.1-py2.6.egg\nose\case.py", line 183, in runTest
    self.test(*self.arg)
  File "f:\work\nose\test_hoge.py", line 41, in test_four
    assert False
AssertionError: 
-------------------- >> begin captured stdout << ---------------------
self.counter 1
test_class.g_counter 5

--------------------- >> end captured stdout << ----------------------

======================================================================
FAIL: test_hoge.test_class.test_three
----------------------------------------------------------------------
Traceback (most recent call last):
  File "f:\Python26\lib\site-packages\nose-0.11.1-py2.6.egg\nose\case.py", line 183, in runTest
    self.test(*self.arg)
  File "f:\work\nose\test_hoge.py", line 35, in test_three
    assert False
AssertionError: 
-------------------- >> begin captured stdout << ---------------------
self.counter 1
test_class.g_counter 5

--------------------- >> end captured stdout << ----------------------

======================================================================
FAIL: test_hoge.test_class.test_two
----------------------------------------------------------------------
Traceback (most recent call last):
  File "f:\Python26\lib\site-packages\nose-0.11.1-py2.6.egg\nose\case.py", line 183, in runTest
    self.test(*self.arg)
  File "f:\work\nose\test_hoge.py", line 29, in test_two
    assert False
AssertionError: 
-------------------- >> begin captured stdout << ---------------------
self.counter 1
test_class.g_counter 5

--------------------- >> end captured stdout << ----------------------

======================================================================
FAIL: test_hoge.test_hoge
----------------------------------------------------------------------
Traceback (most recent call last):
  File "f:\Python26\lib\site-packages\nose-0.11.1-py2.6.egg\nose\case.py", line 183, in runTest
    self.test(*self.arg)
  File "f:\work\nose\test_hoge.py", line 4, in test_hoge
    assert False
AssertionError

----------------------------------------------------------------------
Ran 7 tests in 0.016s

FAILED (failures=5)
  • test_*という名前の関数しかテストされない(パターンあり、詳細はググってください)
  • self.counterが常に1、つまりクラスメソッドのテストはテストの実行とインスタンス生成が対。インスタンスを使い回さない。
  • g_counterが常に5、つまりテスト分だけ事前にインスタンスを生成している。

xUnitのようにクラスを継承する必要も無いし簡単。関数の単体テストはdoctest、ビヘイビアテストはnoseというのが適当かも。