投稿日
2010/12/1 水曜日
PythonでTDD(テスト駆動開発)する方法をググったら、標準のunittestの使い方とか、標準ではないけどnoseの使い方とかがたくさん出てきますが、どれもクラスや関数の使い方の説明に終始してて、実際の開発におけるテストケースを書いたソースファイルのディレクトリ構成や具体的なワークフローについて説明してる所はあまり無く。ググり方が悪いんですかね。
柔軟性が高いというかあまりディレクトリ構成やワークフローに影響を受けないから、各自好きにしろってことなのかな。
しかし、どんな方法にも対応出来るとはいっても、良い方法もあれば悪い方法もあるはず。
てことで自分的に良いと思われる方法・構成を考えてみた。
ただし気に入らない点があるので(後述)、後で解決方法を考える。
で、考えてみたのが以下のようなディレクトリ構成
もちろんディレクトリ名・ファイル名は適当(だけどいくつかの依存関係はある(後述))
ディレクトリの深さも特に制限はない
source ├── a.py ├── libs │ ├── __init__.py │ ├── b.py │ ├── c.py │ └── d.py ├── hoge │ ├── __init__.py │ ├── e.py │ ├── f.py │ ├── g.py │ └── h.py ├── test.py └── tests ├── __init__.py ├── atest.py ├── outputdata │ └── i.txt ├── testdata │ └── j.txt ├── tests_libs │ ├── __init__.py │ ├── btest.py │ ├── ctest.py │ ├── dtest.py │ └── support.py └── tests_hoge ├── __init__.py ├── etest.py ├── ftest.py ├── gtest.py └── htest.py
#!/usr/bin/python # -*- coding: utf-8 -*- from unittest import TextTestRunner, TestCase import tests class AllTestCase(TestCase): def test_all(self): ttr = TextTestRunner(verbosity = 2) ttr.run(tests.get_all_test_suite()) if __name__ == "__main__": atc = AllTestCase() atc.test_all()
test.pyのポイント
#!/usr/bin/python # -*- coding: utf-8 -*- import os, glob from unittest import TestSuite, TestLoader, TextTestRunner CURRENT_DIR = os.path.dirname(os.path.abspath(__file__)) def get_all_test_mods(): '''同階層のテストを全部インポートする''' test_mods = [] pwd = os.getcwd() os.chdir(CURRENT_DIR) try: for file in glob.glob('*test.py'): test_mods.append(__import__(os.path.splitext(file.split('/')[-1])[0], globals(), locals(), [])) return test_mods finally: os.chdir(pwd) def get_all_test_pkgs(): '''テストが定義されたパッケージをインポートする''' test_pkgs = [] pwd = os.getcwd() os.chdir(CURRENT_DIR) try: for file in glob.glob('*/__init__.py'): pkg = __import__(file.split('/')[0], globals(), locals(), []) if getattr(pkg, 'get_all_test_suite', None): test_pkgs.append(pkg) return test_pkgs finally: os.chdir(pwd) def get_all_test_suite(): '''すべてのテストが含まれたTestSuiteを返す''' all_tests = TestSuite() for tm in get_all_test_mods(): suite = TestLoader().loadTestsFromModule(tm) all_tests.addTest(suite) for tp in get_all_test_pkgs(): suite = tp.get_all_test_suite() all_tests.addTest(suite) return all_tests if __name__ == "__main__": ttr = TextTestRunner(verbosity = 2) ttr.run(get_all_test_suite())
__init__.pyのポイント
#!/usr/bin/python # -*- coding: utf-8 -*- from libs import b import unittest class BTestCase(unittest.TestCase): '''Bのテストケース''' def setUp(self): '''テスト前処理''' pass def tearDown(self): '''テスト終了処理''' pass def test1_hoge(self): '''hogeテスト''' # ここにテストコードを書く pass def test2_fuga(self): '''fugaテスト''' # ここにテストコードを書く pass if __name__ == '__main__': unittest.main()
tests_libs/btest.pyの例のポイント
ディレクトリ名・ファイル名は何でもいいのですが、今回の方法だと以下の依存関係があります。
気に入らない点
一応条件は満たしているものの微妙だ…
最近のコメント
名前
しゅごい
Jane Doe
FYI Avoid Annoying Unexpe…
Jane Doe
ご存じとは思いますが、whileには、”~の間”と…
peta_okechan
針金みたいなパーツを引っ張ると外れます。 他の方の…
虎徹ファン交換
虎徹の標準ファンを外す際に、どのようにして外されま…
花粉症対策2019 – 日曜研究室
[…] 花粉症対策についてはこれまで次の記事を書いてきました。https://…
花粉症対策2019 – 日曜研究室
[…] 花粉症対策についてはこれまで次の記事を書いてきました。https://…
花粉症対策2019 – 日曜研究室
[…] 花粉症対策についてはこれまで次の記事を書いてきました。https://…
花粉症対策2019 – 日曜研究室
[…] 花粉症対策についてはこれまで次の記事を書いてきました。https://…
花粉症対策2019 – 日曜研究室
[…] 花粉症対策についてはこれまで次の記事を書いてきました。https://…