ライブラリまたはアプリを作成している場合、単体テストファイルはどこに行きますか?
テストファイルをメインアプリのコードから分離するのは良いことですが、テストするモジュールをインポートするのが難しくなるため、アプリのルートディレクトリ内の「tests」サブディレクトリにそれらを配置するのは厄介です。
ここにベストプラクティスはありますか?
ライブラリまたはアプリを作成している場合、単体テストファイルはどこに行きますか?
テストファイルをメインアプリのコードから分離するのは良いことですが、テストするモジュールをインポートするのが難しくなるため、アプリのルートディレクトリ内の「tests」サブディレクトリにそれらを配置するのは厄介です。
ここにベストプラクティスはありますか?
回答:
ファイルのmodule.py
場合、ユニットテストは通常test_module.py
、Pythonの命名規則に従って呼び出されます。
一般的に受け入れられている場所がいくつかありますtest_module.py
:
module.py
。../tests/test_module.py
(コードディレクトリと同じレベル)。tests/test_module.py
(コードディレクトリの下にあるレベル)。テストを見つけてインポートするのが簡単なため、私は#1を好みます。どのビルドシステムを使用していても、で始まるファイルを実行するように簡単に構成できますtest_
。実際、テスト検出に使用されるデフォルトのunittest
パターンはtest*.py
です。
テストファイルが1つしかない場合は、最上位ディレクトリに配置することをお勧めします。
module/
lib/
__init__.py
module.py
test.py
CLIでテストを実行する
python test.py
多くのテストファイルがある場合は、それをtests
フォルダーに配置します。
module/
lib/
__init__.py
module.py
tests/
test_module.py
test_module_function.py
# test_module.py
import unittest
from lib import module
class TestModule(unittest.TestCase):
def test_module(self):
pass
if __name__ == '__main__':
unittest.main()
CLIでテストを実行する
# In top-level /module/ folder
python -m tests.test_module
python -m tests.test_module_function
unittest discovery
unittest discovery
すべてのテストはパッケージフォルダーにあります。
作成__init__.py
中tests/
フォルダ
module/
lib/
__init__.py
module.py
tests/
__init__.py
test_module.py
test_module_function.py
CLIでテストを実行する
# In top-level /module/ folder
# -s, --start-directory (default current directory)
# -p, --pattern (default test*.py)
python -m unittest discover
pytest
グッドプラクティステストレイアウトのunittest
一般的な方法は、testsディレクトリをモジュール/パッケージと同じ親ディレクトリに置くことです。したがって、モジュールがfoo.pyと呼ばれた場合、ディレクトリレイアウトは次のようになります。
parent_dir/
foo.py
tests/
もちろん、それを行う方法は1つではありません。また、testsサブディレクトリを作成し、絶対インポートを使用してモジュールをインポートすることもできます。
テストをどこに置いても、鼻を使って実行することをお勧めします。Noseはディレクトリをテストして検索します。このようにして、組織的に最も意味のある場所にテストを配置できます。
Pythonプログラムの単体テストを生成するPythoscope(https://pypi.org/project/pythoscope/)を作成するときにも、同じ質問がありました。ディレクトリを選択する前に、Pythonリストのテストで人々に投票したところ、さまざまな意見がありました。最後に、「tests」ディレクトリをソースコードと同じディレクトリに配置することを選択しました。そのディレクトリで、親ディレクトリ内の各モジュールのテストファイルを生成します。
上記のJeremy Cantrellが注記しているように、単体テストもファイルに入れる傾向がありますが、本体にテスト関数を入れるのではなく、すべてを
if __name__ == '__main__':
do tests...
ブロック。これは、テストしているpythonファイルの使用方法の「サンプルコード」としてドキュメントにファイルを追加することになります。
追加すべきですが、非常にタイトなモジュール/クラスを書く傾向があります。モジュールに非常に多数のテストが必要な場合は、別のテストに配置できますが、それでも、次のように追加します。
if __name__ == '__main__':
import tests.thisModule
tests.thisModule.runtests
これにより、ソースコードを読んでいる誰もがテストコードを探す場所を知ることができます。
時々、私はテストの配置のトピックをチェックしていることに気付き、大多数がライブラリコードの横にある別のフォルダー構造を推奨するたびに、引数が同じであり、説得力があるとは限りません。結局、テストモジュールをコアモジュールの横に置きます。
これを行う主な理由は、リファクタリングです。
物事を移動するときは、テストモジュールをコードと一緒に移動する必要があります。テストが別のツリーにある場合、テストを失うのは簡単です。正直に言うと、遅かれ早かれ、django、フラスコなど、まったく異なるフォルダー構造になってしまいます。あなたが気にしないならそれは問題ありません。
あなたが自問すべき主な質問はこれです:
私は書いていますか:
もし:
別のフォルダーとその構造を維持するための余分な労力が適している場合があります。テストが本番環境にデプロイされることに不満を言う人はいません。
しかし、コアフォルダーと混在しているテストを配布から除外するのも同じくらい簡単です。これをsetup.pyに入れます:
find_packages("src", exclude=["*.tests", "*.tests.*", "tests.*", "tests"])
bの場合:
私たちの誰もがそうであるように、再利用可能なライブラリを作成することを望むかもしれませんが、ほとんどの場合、それらのライフはプロジェクトのライフに結びついています。プロジェクトを簡単に維持できることが優先事項です。
次に、適切な作業を行い、モジュールが別のプロジェクトに適している場合は、おそらく、フォークされたり別のライブラリに作成されたりせずに、この新しいプロジェクトにコピーされ、同じフォルダー構造内の横にあるテストが移動します。別のテストフォルダーになった混乱でテストを釣り上げることに比べて簡単です。(そもそもごちゃごちゃにすべきではないと主張するかもしれませんが、ここでは現実的にしましょう)。
ですから、選択はあなた次第ですが、混合テストを使用すると、別のフォルダーを使用する場合とすべて同じことを達成できますが、整頓するための労力は少なくなります。
確立された「ベストプラクティス」があるとは思いません。
テストはアプリコードの外の別のディレクトリに配置しました。次に、すべてのテストを実行する前に、メインアプリディレクトリをsys.pathに追加します(どこからでもモジュールをインポートできるようにします)。これにより、リリース時にメインディレクトリからテストディレクトリを削除する必要がなくなり、時間と労力を節約できます。
os.sys.path.append(os.dirname('..'))
Pythonでのテストフレームワークの開発における私の経験から、Python単体テストを別のディレクトリに置くことをお勧めします。対称的なディレクトリ構造を維持します。これは、単体テストをパッケージ化するのではなく、コアライブラリのみをパッケージ化するのに役立ちます。以下は、概略図で実装されています。
<Main Package>
/ \
/ \
lib tests
/ \
[module1.py, module2.py, [ut_module1.py, ut_module2.py,
module3.py module4.py, ut_module3.py, ut_module.py]
__init__.py]
このようにして、rpmを使用してこれらのライブラリをパッケージ化すると、メインライブラリモジュール(のみ)をパッケージ化できます。これにより、特にアジャイル環境での保守性が向上します。
GitHubでいくつかの主要なPythonプロジェクトをチェックして、いくつかのアイデアを得ることをお勧めします。
コードが大きくなり、ライブラリを追加する場合は、setup.pyと同じディレクトリにテストフォルダーを作成し、各テストタイプ(unittest、integrationなど)のプロジェクトディレクトリ構造をミラー化することをお勧めします。
たとえば、次のようなディレクトリ構造があるとします。
myPackage/
myapp/
moduleA/
__init__.py
module_A.py
moduleB/
__init__.py
module_B.py
setup.py
テストフォルダを追加すると、次のようなディレクトリ構造になります。
myPackage/
myapp/
moduleA/
__init__.py
module_A.py
moduleB/
__init__.py
module_B.py
test/
unit/
myapp/
moduleA/
module_A_test.py
moduleB/
module_B_test.py
integration/
myapp/
moduleA/
module_A_test.py
moduleB/
module_B_test.py
setup.py
適切に記述されたPythonパッケージの多くは、同じ構造を使用しています。非常に良い例は、Botoパッケージです。https://github.com/boto/botoを確認してください
matplotlib
下でそれを持っているmatplotlib/lib/matplotlib/tests
(github.com/matplotlib/matplotlib/tree/...)、sklearn
下でそれを持っているscikitelearn/sklearn/tests
(github.com/scikit-learn/scikit-learn/tree/master/sklearn/tests)
どうやって...
フォルダー構造:
project/
src/
code.py
tests/
setup.py
Setup.pyは、プロジェクトモジュールを含む場所としてsrc /を指し、次に実行します。
setup.py develop
これにより、プロジェクトがサイトパッケージに追加され、作業コピーが示されます。テストを実行するには、次を使用します。
setup.py tests
設定したテストランナーを使用します。
code.py
。トップレベルのディレクトリを「プロジェクト」と呼ぶ方が理にかなっています。
私はトップレベルのテストディレクトリを好みます。これは、インポートがもう少し難しくなることを意味します。そのために私は2つの解決策を持っています:
test_suite='tests.runalltests.suite'
してsetup()
、テストを簡単に実行できます。python setup.py test
PYTHONPATH=. python tests/runalltests.py
以下は、M2Cryptoのコードでそのようなものがサポートされる方法です。
nosetestsを使用してテストを実行したい場合は、少し異なる何かを行う必要があるかもしれません。
テストが単純な場合は、単にそれらをdocstringに入れます-Pythonのほとんどのテストフレームワークはそれを使用できます。
>>> import module
>>> module.method('test')
'testresult'
他のより複雑なテストでは、私はどちらかに入れたい../tests/test_module.py
かでtests/test_module.py
。
「foo」というパッケージを作成するとき、単体テストを別のパッケージ「foo_test」に入れます。モジュールとサブパッケージは、SUTパッケージモジュールと同じ名前になります。たとえば、モジュールfoo.xyのテストはfoo_test.xyにあります。各テストパッケージの__init__.pyファイルには、パッケージのすべてのテストスイートを含むAllTestsスイートが含まれています。setuptoolsは、メインのテストパッケージを指定する便利な方法を提供します。これにより、「python setup.pydevelop」の後に「python setup.py test」または「python setup.py test -s foo_test.x.SomeTestSuite」を使用して、特定のスイートのみ。
テストをテスト対象コード(CUT)と同じディレクトリに配置しました。以下のためfoo.py
のテストになりますfoo_ut.py
または類似。(私はこれらを見つけるためにテスト発見プロセスを微調整します。)
これにより、テストがディレクトリリストのコードのすぐ横に配置され、テストがそこにあることが明らかになり、別のファイルにある場合と同じくらい簡単にテストを開くことができます。(コマンドラインエディターの場合、vim foo*
およびグラフィカルファイルシステムブラウザーを使用する場合は、CUTファイルをクリックしてから、すぐ隣のテストファイルをクリックします。)
他の人が指摘している、これはまた、それが簡単にリファクタリングするとの使用のためのコードを抽出する他の場所でそれが今まで必要である必要があります。
まったく別のディレクトリツリーにテストを置くという考えは本当に嫌いです。開発者がCUTでファイルを開いているときにテストを開くことが必要以上に難しくなるのはなぜですか?大多数の開発者がテストの作成や微調整に熱心で、バリアを言い訳として使用する代わりに、バリアを無視するわけではありません。(私の経験では、まったく逆です。あなたができる限り簡単にしても、テストを書くことに煩わされない多くの開発者を知っています。)
私は最近Pythonでプログラミングを始めたので、まだベストプラクティスを見つける機会はまだありませんでした。しかし、私は行ってすべてのテストを見つけて実行するモジュールを書きました。
ので、私は持っています:
app / appfile.py テスト/ appfileTest.py
大規模なプロジェクトに進むにつれ、どうなるかを確認する必要があります。