どんな走行の全てのPythonユニットテストディレクトリ?
-
20-09-2019 - |
質問
いディレクトリを含む私のPythonユニット。各ユニットテストモジュールは次の形をしている test_*.py.テーマとしておくというファイルと all_test.py まだ推測し、すべてのファイル上記の試験の形式を返します。いた方法によ両方という点で共通しています。私の方に拡げていきたいと思っていう知っていて、実際にいます。
私の最初の勇敢な試みと言えば...やっぱり"までの輸入全ての試験モジュールのファイルを呼び出す unittest.main()
doodadです。 やがっておもしろかったです。
import glob
import unittest
testSuite = unittest.TestSuite()
test_file_strings = glob.glob('test_*.py')
module_strings = [str[0:len(str)-3] for str in test_file_strings]
if __name__ == "__main__":
unittest.main()
ことはできませんでしたが、結果んでした:
$ python all_test.py
----------------------------------------------------------------------
Ran 0 tests in 0.000s
OK
私の第二ってみたら、もゃんでいきたいと思っていないこの試験はもとよりマニュアル""ファッション。うにしようとするという。
import glob
import unittest
testSuite = unittest.TestSuite()
test_file_strings = glob.glob('test_*.py')
module_strings = [str[0:len(str)-3] for str in test_file_strings]
[__import__(str) for str in module_strings]
suites = [unittest.TestLoader().loadTestsFromName(str) for str in module_strings]
[testSuite.addTest(suite) for suite in suites]
print testSuite
result = unittest.TestResult()
testSuite.run(result)
print result
#Ok, at this point I have a result
#How do I display it as the normal unit test command line output?
if __name__ == "__main__":
unittest.main()
これも動作しなかったが、どうもそうらしい。
$ python all_test.py
<unittest.TestSuite tests=[<unittest.TestSuite tests=[<unittest.TestSuite tests=[<test_main.TestMain testMethod=test_respondes_to_get>]>]>]>
<unittest.TestResult run=1 errors=0 failures=0>
----------------------------------------------------------------------
Ran 0 tests in 0.000s
OK
いのか、実行することができる。私はこうしてい run=1
, このようにすべき run=2
, ものです。い方が分からない通過および結果の表示をメイン?または方法については基本的に取得しんでいただき、このファイルなど、すべての単体テスト(ユニットテストにこのディレクトリ?
解決
あなたはあなたのためにこれを行うだろうテストランナーを使用することができます。 鼻には、例えば非常に良いです。実行すると、それは現在のツリーでテストを見つけ、それらを実行します。
更新:
ここに私の前の鼻の日からいくつかのコードです。おそらく、モジュール名の明示的なリストを望んでいない、多分残りはあなたに有用であろう。
testmodules = [
'cogapp.test_makefiles',
'cogapp.test_whiteutils',
'cogapp.test_cogapp',
]
suite = unittest.TestSuite()
for t in testmodules:
try:
# If the module defines a suite() function, call it to get the suite.
mod = __import__(t, globals(), locals(), ['suite'])
suitefn = getattr(mod, 'suite')
suite.addTest(suitefn())
except (ImportError, AttributeError):
# else, just load all the test cases from the module.
suite.addTest(unittest.defaultTestLoader.loadTestsFromName(t))
unittest.TextTestRunner().run(suite)
他のヒント
はPython 2.7以降では、新しいコードを記述するか、これを行うには、サードパーティ製のツールを使用する必要はありません。コマンドラインを介して再帰テストの実行が内蔵されています。
python -m unittest discover <test_directory>
# or
python -m unittest discover -s <directory> -p '*_test.py'
あなたはのpython 2.7 ので詳細を読むことができます またはのpython 3.xののunittestのマニュアルを参照してください。
これは、unittestのから直接可能になりました。
を発見します。import unittest
loader = unittest.TestLoader()
start_dir = 'path/to/your/test/files'
suite = loader.discover(start_dir)
runner = unittest.TextTestRunner()
runner.run(suite)
Python 3 で使用している場合 unittest.TestCase
:
- 空の(またはそうでない)ものが必要です
__init__.py
あなたのファイルにtest
ディレクトリ (しなければならない 名前が付けられるtest/
) - 内部のテストファイル
test/
パターンを合わせるtest_*.py
. 。以下のサブディレクトリ内に置くことができます。test/
, 、それらのサブディレクトリには任意の名前を付けることができます。
その後、次のコマンドを使用してすべてのテストを実行できます。
python -m unittest
終わり!100 行未満のソリューション。他の Python 初心者がこれを見つけて時間を節約できることを願っています。
さてビット上記のコードを研究することによって(特にTextTestRunner
とdefaultTestLoader
を使用して)、私はかなり近づくことができました。結局私はまた、1つだけのスイートコンストラクタにすべてのテストスイートを渡すのではなく、私の他の問題を修正した、「手動」にそれらを追加することによって、自分のコードを修正しました。だからここに私の解決策はあります。
import glob
import unittest
test_files = glob.glob('test_*.py')
module_strings = [test_file[0:len(test_file)-3] for test_file in test_files]
suites = [unittest.defaultTestLoader.loadTestsFromName(test_file) for test_file in module_strings]
test_suite = unittest.TestSuite(suites)
test_runner = unittest.TextTestRunner().run(test_suite)
ええ、おそらく、これを行うことよりも、ただの鼻を使用する方が簡単ですが、それはポイント以外にもあります。
あなたは、さまざまなテストケースクラスからのすべてのテストを実行すると、あなたが明示的にそれらを指定させていただきます場合は、このようにそれを行うことができます:
from unittest import TestLoader, TextTestRunner, TestSuite
from uclid.test.test_symbols import TestSymbols
from uclid.test.test_patterns import TestPatterns
if __name__ == "__main__":
loader = TestLoader()
tests = [
loader.loadTestsFromTestCase(test)
for test in (TestSymbols, TestPatterns)
]
suite = TestSuite(tests)
runner = TextTestRunner(verbosity=2)
runner.run(suite)
uclid
は私のプロジェクトとTestSymbols
とTestPatterns
あるTestCase
のサブクラスです。
私は、コードの(最小の、と思う)数ラインでこの結果を達成するためにdiscover
方法及びload_tests
のオーバーロードを使用しています
def load_tests(loader, tests, pattern):
''' Discover and load all unit tests in all files named ``*_test.py`` in ``./src/``
'''
suite = TestSuite()
for all_test_suite in unittest.defaultTestLoader.discover('src', pattern='*_tests.py'):
for test_suite in all_test_suite:
suite.addTests(test_suite)
return suite
if __name__ == '__main__':
unittest.main()
のようなファイブ何かの実行
Ran 27 tests in 0.187s
OK
それは迷惑なんだ、私は様々なアプローチを試みたが、すべては、欠陥のあるように見えるか、私はメイクにいくつかのコードを持っています。しかし、Linuxでとても便利な方法があります、それは特定のパターンを介してすべてのテストを発見し、それらを一つずつを起動するだけです。
find . -name 'Test*py' -exec python '{}' \;
そして最も重要な、それは間違いなく動作します。
の場合 パッケージ 図書館、アプリケーションによってお使いのことを思い出します。 setuptools
まで承ります。.
このコマンドプロジェクトの試験が必要に包まれた
unittest
試験スイートは、機能テストケースクラスのクラスやメソッド、またはモジュールやパッケージを含むTestCase
ます。場合は、名前付きスイートはモジュールのモジュールadditional_tests()
機能呼ばれる、のでなければなunittest.TestSuite
追加される試験です。場合は、名前付きスイートはパッケージには、 当submodules、サブパッケージには再帰的に追加され、全体の試験スイート.
かえでがインストールの試験パッケージには、のように:
setup(
# ...
test_suite = 'somepkg.test'
)
走 python setup.py test
.
ファイルに基づく発見が問題になることがありPython3の場合を除き避ける相対的な輸入テストスイートで discover
使用ファイルにサポートいたします。にも対応オプション top_level_dir
, があったかも無限再帰。う簡単に解決のための非パッケージコードは、以下の __init__.py
試験パッケージ参照 load_testsプロトコル).
import unittest
from . import foo, bar
def load_tests(loader, tests, pattern):
suite = unittest.TestSuite()
suite.addTests(loader.loadTestsFromModule(foo))
suite.addTests(loader.loadTestsFromModule(bar))
return suite
私はPyDevは/ LiClipseを使用して、本当にGUIから一度にすべてのテストを実行する方法を考え出したていません。 (編集:あなたは右のルートテストフォルダをクリックしてRun as -> Python unit-test
を選択し、
これは私の現在の回避策は次のとおりです。
import unittest
def load_tests(loader, tests, pattern):
return loader.discover('.')
if __name__ == '__main__':
unittest.main()
私は私のテストディレクトリにall
と呼ばれるモジュールにこのコードを置きます。私はLiClipseからユニットテストとして、このモジュールを実行する場合は、すべてのテストが実行されます。私は、特定のか失敗したテストを繰り返すように頼む場合のみテストが実行されます。それは私のコマンドラインテストランナーのいずれか(nosetests)に干渉しない - それは無視されます。
あなたは、あなたのプロジェクトの設定に基づいてdiscover
する引数を変更する必要があります。
私は、ネストされたテストモジュールのサポートを追加するのスティーブンCagleの回答に基づいています。
import fnmatch
import os
import unittest
def all_test_modules(root_dir, pattern):
test_file_names = all_files_in(root_dir, pattern)
return [path_to_module(str) for str in test_file_names]
def all_files_in(root_dir, pattern):
matches = []
for root, dirnames, filenames in os.walk(root_dir):
for filename in fnmatch.filter(filenames, pattern):
matches.append(os.path.join(root, filename))
return matches
def path_to_module(py_file):
return strip_leading_dots( \
replace_slash_by_dot( \
strip_extension(py_file)))
def strip_extension(py_file):
return py_file[0:len(py_file) - len('.py')]
def replace_slash_by_dot(str):
return str.replace('\\', '.').replace('/', '.')
def strip_leading_dots(str):
while str.startswith('.'):
str = str[1:len(str)]
return str
module_names = all_test_modules('.', '*Tests.py')
suites = [unittest.defaultTestLoader.loadTestsFromName(mname) for mname
in module_names]
testSuite = unittest.TestSuite(suites)
runner = unittest.TextTestRunner(verbosity=1)
runner.run(testSuite)
コードがロードされている.
ファイル用*Tests.py
のすべてのサブディレクトリを検索します。これは、各*Tests.py
が次々と順番にロードされて実行される単一のクラスの*Tests(unittest.TestCase)
を含むように期待しています。
これは、ディレクトリ/モジュールの任意の深いネスティングで動作しますが、ニーズの間の各ディレクトリには、少なくとも空__init__.py
ファイルを格納します。このテストは、(replace_slash_by_dot
参照)ドットでスラッシュ(またはバックスラッシュ)を置き換えることにより、ネストされたモジュールをロードすることができます。
テスト ディスカバリは完全なテーマであるように見えるため、テスト ディスカバリのための専用のフレームワークがいくつかあります。
詳細はこちらをご覧ください: https://wiki.python.org/moin/PythonTestingToolsTaxonomy
このBASHスクリプトは関係なく、あなたが何であるかの作業ディレクトリ、ファイルシステム内のどこからでもtestディレクトリのunittestのpythonを実行しません:。そのtest
ディレクトリが配置されている場所の作業ディレクトリは常に
のすべてのテスト、独立した$ PWD の
あなたはどこ(discover -s
オプションを使用して)、それを教えてくれない限り、は、Pythonのunittestモジュールは、現在のディレクトリに敏感である。
./src
または./example
作業ディレクトリに滞在するときに便利ですし、迅速な全体的なユニットテストを必要とします:
#!/bin/bash
this_program="$0"
dirname="`dirname $this_program`"
readlink="`readlink -e $dirname`"
python -m unittest discover -s "$readlink"/test -v
を選択したテスト、独立した$ PWD の
私は、このユーティリティファイル名:runone.py
をし、このようにそれを使用します
runone.py <test-python-filename-minus-dot-py-fileextension>
#!/bin/bash
this_program="$0"
dirname="`dirname $this_program`"
readlink="`readlink -e $dirname`"
(cd "$dirname"/test; python -m unittest $1)
製造時の負担パッケージ/メモリー・オーバーヘッドにtest/__init__.py
ファイルの必要はありません。
ここに私のアプローチは、実行するために Aラッパーに作成することですコマンドラインからテストます:
#!/usr/bin/env python3
import os, sys, unittest, argparse, inspect, logging
if __name__ == '__main__':
# Parse arguments.
parser = argparse.ArgumentParser(add_help=False)
parser.add_argument("-?", "--help", action="help", help="show this help message and exit" )
parser.add_argument("-v", "--verbose", action="store_true", dest="verbose", help="increase output verbosity" )
parser.add_argument("-d", "--debug", action="store_true", dest="debug", help="show debug messages" )
parser.add_argument("-h", "--host", action="store", dest="host", help="Destination host" )
parser.add_argument("-b", "--browser", action="store", dest="browser", help="Browser driver.", choices=["Firefox", "Chrome", "IE", "Opera", "PhantomJS"] )
parser.add_argument("-r", "--reports-dir", action="store", dest="dir", help="Directory to save screenshots.", default="reports")
parser.add_argument('files', nargs='*')
args = parser.parse_args()
# Load files from the arguments.
for filename in args.files:
exec(open(filename).read())
# See: http://codereview.stackexchange.com/q/88655/15346
def make_suite(tc_class):
testloader = unittest.TestLoader()
testnames = testloader.getTestCaseNames(tc_class)
suite = unittest.TestSuite()
for name in testnames:
suite.addTest(tc_class(name, cargs=args))
return suite
# Add all tests.
alltests = unittest.TestSuite()
for name, obj in inspect.getmembers(sys.modules[__name__]):
if inspect.isclass(obj) and name.startswith("FooTest"):
alltests.addTest(make_suite(obj))
# Set-up logger
verbose = bool(os.environ.get('VERBOSE', args.verbose))
debug = bool(os.environ.get('DEBUG', args.debug))
if verbose or debug:
logging.basicConfig( stream=sys.stdout )
root = logging.getLogger()
root.setLevel(logging.INFO if verbose else logging.DEBUG)
ch = logging.StreamHandler(sys.stdout)
ch.setLevel(logging.INFO if verbose else logging.DEBUG)
ch.setFormatter(logging.Formatter('%(asctime)s %(levelname)s: %(name)s: %(message)s'))
root.addHandler(ch)
else:
logging.basicConfig(stream=sys.stderr)
# Run tests.
result = unittest.TextTestRunner(verbosity=2).run(alltests)
sys.exit(not result.wasSuccessful())
簡略化のために、私の非 PEP8 のコーディング標準を言い訳してくださいます。
次に、あなたはすべてのあなたのテストのための共通コンポーネントのBaseTestクラスを作成することができますので、あなたのテストのそれぞれは、単純に次のようになります:
from BaseTest import BaseTest
class FooTestPagesBasic(BaseTest):
def test_foo(self):
driver = self.driver
driver.get(self.base_url + "/")
あなたは、単にコマンドライン引数の一部、例えばとしてのテストを指定し、実行するには:ます。
./run_tests.py -h http://example.com/ tests/**/*.py