Python コードのユニットテスト2016年1月26日 | |
はじめにPython コードのユニットテストについて。 環境
※MinGW にも Python が入っているので、Anaconda のほうを使うようにパスを設定している。 例例として、以下のようなコードを考える。 func.py def abs(x): if x >= 0: return x else: return -x def positive(x): if x > 0: return True else: return False テストを書くテストは以下のように書く。 func_test.py from unittest import TestCase, main from func import * class FuncTest(TestCase): def setUp(self): pass def tearDown(self): pass def test_abs(self): self.assertEqual(abs(1), 1) self.assertEqual(abs(-1), 1) def test_positive(self): self.assertTrue(positive(1)) self.assertTrue(not positive(-1)) if __name__ == '__main__': main() TestCase を継承したクラスを作り、その中にテストを書く。setUp() と tearDown() はそれぞれテスト前とテスト後に実行される関数である。assertEqual() は値が等しいことをチェックする関数で、assertTrue() は値が真であることをチェックする関数である。 テストの実行テストを実行するには、次のようにする。 $ python -m unittest -v func_test.FuncTest test_abs (func_test.FuncTest) ... ok test_positive (func_test.FuncTest) ... ok ---------------------------------------------------------------------- Ran 2 tests in 0.000s OK オプション "-v" は詳細表示の指定である。 テストに失敗すると、次のようになる。 $ python -m unittest -v func_test.FuncTest test_abs (func_test.FuncTest) ... FAIL test_positive (func_test.FuncTest) ... ok ====================================================================== FAIL: test_abs (func_test.FuncTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "func_test.py", line 14, in test_abs self.assertEqual(abs(-1), 1) AssertionError: -1 != 1 ---------------------------------------------------------------------- Ran 2 tests in 0.001s FAILED (failures=1) カレントディレクトリにあるテストコードを含むファイルをすべて実行させることもできる。テストコードを含むファイル名を "*_test.py" とすると、以下のように実行する。 $ $ python -m unittest discover -p "*_test.py" -v オプション "-p" でテストコードのファイル名のパターンを指定している。 nose の利用nose というテストツールを使うこともできる。 上のテストを次のように書ける。 from unittest import TestCase from nose.tools import eq_, ok_ from func import * class FuncTest(TestCase): def setUp(self): pass def tearDown(self): pass def test_abs(self): eq_(abs(1), 1) eq_(abs(-1), 1) def test_positive(self): ok_(positive(1)) ok_(not positive(-1)) eq_() は assertEqual() の代り、ok_() は assertTrue() の代りである。 テストは次のように実行する。 $ nosetests -v func_test.py test_abs (func_test.FuncTest) ... ok test_positive (func_test.FuncTest) ... ok ---------------------------------------------------------------------- Ran 2 tests in 0.000s OK オプション "-v" は詳細表示の指定である。nosetests はテストの標準出力を出力させないため、もし出力させたい場合はオプション "-s" を指定する。nosetests は、ファイル名を指定しなければ、カレントディレクトリにある名前からしてテストコードと思われるファイルの中からテストを探して実行してくれる。 テストが失敗した時点でテストを停止したい場合は、オプションで "-x" を指定する。 $ nosetests -v -x test_abs (func_test.FuncTest) ... FAIL ====================================================================== FAIL: test_abs (func_test.FuncTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\msys64\home\yuyu\unittest\nose\func_test.py", line 15, in test_abs eq_(abs(-1), 1) AssertionError: -1 != 1 ---------------------------------------------------------------------- Ran 1 test in 0.006s FAILED (failures=1) コードカバレッジの計測Coverage があれば、コードカバレッジを測ることができる。 Coverage のインストールは次のようにする。 $ pip install coverage コードカバレッジを計測するには、テストを次のように実行する。 $ coverage run func_test.py 計測結果は次のように得られる。 $ coverage report Name Stmts Miss Cover ---------------------------------- func.py 8 0 100% func_test.py 15 0 100% ---------------------------------- TOTAL 23 0 100% もしテストの範囲が十分でないと、次のようになる。 $ coverage report Name Stmts Miss Cover ---------------------------------- func.py 8 2 75% func_test.py 13 0 100% ---------------------------------- TOTAL 21 2 90% 次のようにすると、HTML を生成してくれる。 $ coverage html htmlconv/index.html をブラウザで開く。この情報を見ると、下図のように、どこを通り損ねているか一目瞭然である。 ![]() Coverage の情報を初期化したい場合は、次のようにする。 $ coverage erase nose の場合nosetests のオプションで "--with-coverage" を指定すると、Coverage を実行してくれる。 $ nosetests -v --with-coverage test_abs (func_test.FuncTest) ... ok test_positive (func_test.FuncTest) ... ok Name Stmts Miss Cover Missing --------------------------------------- func.py 8 0 100% ---------------------------------------------------------------------- Ran 2 tests in 0.009s OK オプション "--cover-html" で HTML 生成を、"--cover-erase" で実行前に erase を実行してくれる。 参考 | |
PENGUINITIS |