问题:如何在目录中运行所有Python单元测试?
我有一个目录,其中包含我的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
,但这是进步。但是如何传递结果并将其显示给main?还是我基本上如何使它工作,以便我可以运行该文件,然后运行此目录中的所有单元测试?
I have a directory that contains my Python unit tests. Each unit test module is of the form test_*.py. I am attempting to make a file called all_test.py that will, you guessed it, run all files in the aforementioned test form and return the result. I have tried two methods so far; both have failed. I will show the two methods, and I hope someone out there knows how to actually do this correctly.
For my first valiant attempt, I thought “If I just import all my testing modules in the file, and then call this unittest.main()
doodad, it will work, right?” Well, turns out I was wrong.
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()
This did not work, the result I got was:
$ python all_test.py
----------------------------------------------------------------------
Ran 0 tests in 0.000s
OK
For my second try, I though, ok, maybe I will try to do this whole testing thing in a more “manual” fashion. So I attempted to do that below:
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()
This also did not work, but it seems so close!
$ 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
I seem to have a suite of some sort, and I can execute the result. I am a little concerned about the fact that it says I have only run=1
, seems like that should be run=2
, but it is progress. But how do I pass and display the result to main? Or how do I basically get it working so I can just run this file, and in doing so, run all the unit tests in this directory?
回答 0
使用Python 2.7及更高版本,您无需编写新代码或使用第三方工具即可完成此操作。内置了通过命令行执行递归测试的功能。__init__.py
在您的测试目录中放置:
python -m unittest discover <test_directory>
# or
python -m unittest discover -s <directory> -p '*_test.py'
您可以在python 2.7
或python 3.x unittest文档中阅读更多内容。
With Python 2.7 and higher you don’t have to write new code or use third-party tools to do this; recursive test execution via the command line is built-in. Put an __init__.py
in your test directory and:
python -m unittest discover <test_directory>
# or
python -m unittest discover -s <directory> -p '*_test.py'
You can read more in the python 2.7
or python 3.x unittest documentation.
回答 1
您可以使用可以为您完成此任务的测试运行程序。 例如鼻子很好。运行时,它将在当前树中找到测试并运行它们。
更新:
这是我前鼻时期的一些代码。您可能不希望使用模块名称的明确列表,但是其余的名称可能对您有用。
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)
You could use a test runner that would do this for you. nose is very good for example. When run, it will find tests in the current tree and run them.
Updated:
Here’s some code from my pre-nose days. You probably don’t want the explicit list of module names, but maybe the rest will be useful to you.
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)
回答 2
在python 3中,如果您使用的是unittest.TestCase
:
- 您的目录中必须有一个空(或其他)
__init__.py
文件test
(必须命名为test/
)
- 您的测试文件
test/
与模式匹配test_*.py
。它们可以位于下方的子目录中test/
,并且这些子目录可以命名为任何东西。
然后,您可以使用以下命令运行所有测试:
python -m unittest
做完了!解决方案少于100行。希望其他python初学者可以通过查找此方法节省时间。
In python 3, if you’re using unittest.TestCase
:
- You must have an empty (or otherwise)
__init__.py
file in your test
directory (must be named test/
)
- Your test files inside
test/
match the pattern test_*.py
. They can be inside a subdirectory under test/
, and those subdirs can be named as anything.
Then, you can run all the tests with:
python -m unittest
Done! A solution less than 100 lines. Hopefully another python beginner saves time by finding this.
回答 3
现在,可以直接从unittest:unittest.TestLoader.discover进行此操作。
import unittest
loader = unittest.TestLoader()
start_dir = 'path/to/your/test/files'
suite = loader.discover(start_dir)
runner = unittest.TextTestRunner()
runner.run(suite)
This is now possible directly from unittest: unittest.TestLoader.discover.
import unittest
loader = unittest.TestLoader()
start_dir = 'path/to/your/test/files'
suite = loader.discover(start_dir)
runner = unittest.TextTestRunner()
runner.run(suite)
回答 4
通过研究上面的代码(特别是使用TextTestRunner
和defaultTestLoader
),我可以很接近了。最终,我通过仅将所有测试套件传递给单个套件的构造函数,而不是“手动”添加它们来修复了我的代码,从而解决了其他问题。所以这是我的解决方案。
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)
是的,使用鼻子可能比这样做更容易,但这不重要。
Well by studying the code above a bit (specifically using TextTestRunner
and defaultTestLoader
), I was able to get pretty close. Eventually I fixed my code by also just passing all test suites to a single suites constructor, rather than adding them “manually”, which fixed my other problems. So here is my solution.
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)
Yeah, it is probably easier to just use nose than to do this, but that is besides the point.
回答 5
如果要运行各种测试用例类中的所有测试,并且很乐意明确指定它们,则可以这样做:
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
。
If you want to run all the tests from various test case classes and you’re happy to specify them explicitly then you can do it like this:
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)
where uclid
is my project and TestSymbols
and TestPatterns
are subclasses of TestCase
.
回答 6
我使用了该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
I have used the discover
method and an overloading of load_tests
to achieve this result in a (minimal, I think) number lines of code:
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()
Execution on fives something like
Ran 27 tests in 0.187s
OK
回答 7
我尝试了各种方法,但似乎都存在缺陷,或者我必须编写一些代码,这很烦人。但是在Linux下,有一种简便的方法,就是简单地通过某种模式找到每个测试,然后逐个调用它们。
find . -name 'Test*py' -exec python '{}' \;
最重要的是,它肯定有效。
I tried various approaches but all seem flawed or I have to makeup some code, that’s annoying. But there’s a convinient way under linux, that is simply to find every test through certain pattern and then invoke them one by one.
find . -name 'Test*py' -exec python '{}' \;
and most importantly, it definitely works.
回答 8
对于打包的库或应用程序,您不想这样做。setuptools
会为你做。
要使用此命令,您的项目的测试必须unittest
通过函数,TestCase类或方法或包含TestCase
类的模块或包来包装在测试套件中。如果命名套件是一个模块,并且该模块具有一个additional_tests()
功能,则将其调用,并将结果(必须为unittest.TestSuite
)添加到要运行的测试中。如果命名套件是一个包,则将所有子模块和子包递归地添加到整个测试套件中。
只需告诉它您的根测试包在哪里,例如:
setup(
# ...
test_suite = 'somepkg.test'
)
然后跑 python setup.py test
。
除非您避免在测试套件中进行相对导入,否则在Python 3中基于文件的发现可能会出现问题,因为会discover
使用文件导入。即使它支持optional 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
In case of a packaged library or application, you don’t want to do it. setuptools
will do it for you.
To use this command, your project’s tests must be wrapped in a unittest
test suite by either a function, a TestCase class or method, or a module or package containing TestCase
classes. If the named suite is a module, and the module has an additional_tests()
function, it is called and the result (which must be a unittest.TestSuite
) is added to the tests to be run. If the named suite is a package, any submodules and subpackages are recursively added to the overall test suite.
Just tell it where your root test package is, like:
setup(
# ...
test_suite = 'somepkg.test'
)
And run python setup.py test
.
File-based discovery may be problematic in Python 3, unless you avoid relative imports in your test suite, because discover
uses file import. Even though it supports optional top_level_dir
, but I had some infinite recursion errors. So a simple solution for a non-packaged code is to put the following in __init__.py
of your test package (see load_tests Protocol).
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
回答 9
我使用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的单元测试形式运行此模块,则将运行所有测试。如果我只要求重复特定或失败的测试,则仅运行那些测试。它也不会干扰我的命令行测试运行程序(noestests)-被忽略。
您可能需要discover
根据项目设置将参数更改为。
I use PyDev/LiClipse and haven’t really figured out how to run all tests at once from the GUI. (edit: you right click the root test folder and choose Run as -> Python unit-test
This is my current workaround:
import unittest
def load_tests(loader, tests, pattern):
return loader.discover('.')
if __name__ == '__main__':
unittest.main()
I put this code in a module called all
in my test directory. If I run this module as a unittest from LiClipse then all tests are run. If I ask to only repeat specific or failed tests then only those tests are run. It doesn’t interfere with my commandline test runner either (nosetests) — it’s ignored.
You may need to change the arguments to discover
based on your project setup.
回答 10
根据Stephen 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
)。
Based on the answer of Stephen Cagle I added support for nested test modules.
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)
The code searches all subdirectories of .
for *Tests.py
files which are then loaded. It expects each *Tests.py
to contain a single class *Tests(unittest.TestCase)
which is loaded in turn and executed one after another.
This works with arbitrary deep nesting of directories/modules, but each directory in between needs to contain an empty __init__.py
file at least. This allows the test to load the nested modules by replacing slashes (or backslashes) by dots (see replace_slash_by_dot
).
回答 11
这是一个老问题,但现在(2019年)对我有用的是:
python -m unittest *_test.py
我所有的测试文件都与源文件位于同一文件夹中,并以结尾_test
。
This is an old question, but what worked for me now (in 2019) is:
python -m unittest *_test.py
All my test files are in the same folder as the source files and they end with _test
.
回答 12
回答 13
无论您位于哪个工作目录中,此BASH脚本都将从文件系统中的任何位置执行python unittest测试目录:其工作目录始终test
位于该目录所在的位置。
所有测试,独立$ PWD
unittest Python模块对您的当前目录敏感,除非您告诉它当前位置(使用discover -s
选项)。
当位于./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
在生产过程中不需要文件来负担您的程序包/内存开销。
This BASH script will execute the python unittest test directory from ANYWHERE in the file system, no matter what working directory you are in: its working directory always be where that test
directory is located.
ALL TESTS, independent $PWD
unittest Python module is sensitive to your current directory, unless you tell it where (using discover -s
option).
This is useful when staying in the ./src
or ./example
working directory and you need a quick overall unit test:
#!/bin/bash
this_program="$0"
dirname="`dirname $this_program`"
readlink="`readlink -e $dirname`"
python -m unittest discover -s "$readlink"/test -v
SELECTED TESTS, independent $PWD
I name this utility file: runone.py
and use it like this:
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)
No need for a test/__init__.py
file to burden your package/memory-overhead during production.
回答 14
这是我创建包装器以从命令行运行测试的方法:
#!/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
Here is my approach by creating a wrapper to run tests from the command line:
#!/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())
For sake of simplicity, please excuse my non-PEP8 coding standards.
Then you can create BaseTest class for common components for all your tests, so each of your test would simply look like:
from BaseTest import BaseTest
class FooTestPagesBasic(BaseTest):
def test_foo(self):
driver = self.driver
driver.get(self.base_url + "/")
To run, you simply specifying tests as part of the command line arguments, e.g.:
./run_tests.py -h http://example.com/ tests/**/*.py