说我有一个这样的测试套件:
class SafeTests(unittest.TestCase):
# snip 20 test functions
class BombTests(unittest.TestCase):
# snip 10 different test cases
我目前正在做以下事情:
suite = unittest.TestSuite()
loader = unittest.TestLoader()
safetests = loader.loadTestsFromTestCase(SafeTests)
suite.addTests(safetests)
if TARGET != 'prod':
unsafetests = loader.loadTestsFromTestCase(BombTests)
suite.addTests(unsafetests)
unittest.TextTestRunner().run(suite)
我有一个重大问题,一个有趣的观点
我有大量不同的应用程序正在公开这些测试 套房通过入口点。
我希望能够在所有已安装的内容中聚合这些自定义测试 应用程序,所以我不能只是使用一个聪明的命名约定。我不 特别关心这些通过入口点暴露,但我 做关心能否跨应用程序运行测试 站点包。 (不仅仅是导入......每个模块。)
我不关心维护当前的依赖关系
unittest.TestCase
,诋毁这种依赖性实际上是一个目标。
编辑这是为了确认@ Oleksiy关于将args传递给的观点
事实上,nose.run
确实可以解决一些问题。
不工作的事情:
这种脆弱是荒谬的,如果你有改进它的想法我欢迎 评论,或我设置 a github repo with my experiments trying to get this to work
除此之外,以下工作,包括拾取多个项目 安装到site-packages中:
#!python
import importlib, os, sys
import nose
def runtests():
modnames = []
dirs = set()
for modname in sys.argv[1:]:
modnames.append(modname)
mod = importlib.import_module(modname)
fname = mod.__file__
dirs.add(os.path.dirname(fname))
modnames = list(dirs) + modnames
nose.run(argv=modnames)
if __name__ == '__main__':
runtests()
如果保存到runtests.py
文件中,则在运行时执行正确的操作:
runtests.py project.tests otherproject.tests
答案 0 :(得分:4)
对于鼻子,您可以使用attribute插件进行两个测试并选择运行哪个测试,这对于选择要运行的测试非常有用。我会保留两个测试并为它们分配属性:
from nose.plugins.attrib import attr
@attr("safe")
class SafeTests(unittest.TestCase):
# snip 20 test functions
class BombTests(unittest.TestCase):
# snip 10 different test cases
对于你的生产代码,我只需要用nosetests -a safe
调用nose,或者在你的os生产测试环境中设置NOSE_ATTR=safe
,或者在nose对象上调用run方法在python中用{{1}本地运行它基于-a
:
TARGET
最后,如果由于某种原因未发现您的测试,您可以使用import sys
import nose
if __name__ == '__main__':
module_name = sys.modules[__name__].__file__
argv = [sys.argv[0], module_name]
if TARGET == 'prod':
argv.append('-a slow')
result = nose.run(argv=argv)
属性(@istest
)明确标记为测试
答案 1 :(得分:1)
这结果是一团糟:鼻子几乎完全使用了
TestLoader.load_tests_from_names
函数(它是唯一函数在其中测试过的
unit_tests/test_loader
)
因为我想从任意python对象实际加载东西我
似乎需要自己编写一个使用什么样的加载函数。
然后,另外,要像nosetests
脚本一样正确地工作
我需要导入大量的东西。我完全不确定这一点
是最好的做事方式,甚至不是。但这是一个被剥夺了
对我有用的例子(没有错误检查,不那么详细):
import sys
import types
import unittest
from nose.config import Config, all_config_files
from nose.core import run
from nose.loader import TestLoader
from nose.suite import ContextSuite
from nose.plugins.manager import PluginManager
from myapp import find_test_objects
def load_tests(config, obj):
"""Load tests from an object
Requires an already configured nose.config.Config object.
Returns a nose.suite.ContextSuite so that nose can actually give
formatted output.
"""
loader = TestLoader()
kinds = [
(unittest.TestCase, loader.loadTestsFromTestCase),
(types.ModuleType, loader.loadTestsFromModule),
(object, loader.loadTestsFromTestClass),
]
tests = None
for kind, load in kinds.items():
if isinstance(obj, kind) or issubclass(obj, kind):
log.debug("found tests for %s as %s", obj, kind)
tests = load(obj)
break
suite = ContextSuite(tests=tests, context=obj, config=config)
def main():
"Actually configure the nose config object and run the tests"
config = Config(files=all_config_files(), plugins=PluginManager())
config.configure(argv=sys.argv)
tests = []
for group in find_test_objects():
tests.append(load_tests(config, group))
run(suite=tests)
答案 2 :(得分:0)
如果你的问题是,“如何让pytest'看'测试?',你需要在每个测试文件和每个测试用例(即函数)之前加上'test_'。然后,只需在pytest命令行上传递要搜索的目录,它将递归搜索匹配'test_XXX.py'的文件,从中收集'test_XXX'函数并运行它们。
至于文档,您可以尝试启动here.
如果您不喜欢默认的pytest测试集合方法,可以使用方向here.
对其进行自定义答案 3 :(得分:0)
如果您愿意更改代码以生成py.test
"套件" (我的定义)而不是单元测试套件(技术术语),您可以轻松地这样做。创建一个名为conftest.py
的文件,如下面的存根
import pytest
def pytest_collect_file(parent, path):
if path.basename == "foo":
return MyFile(path, parent)
class MyFile(pytest.File):
def collect(self):
myname="foo"
yield MyItem(myname, self)
yield MyItem(myname, self)
class MyItem(pytest.Item):
SUCCEEDED=False
def __init__(self, name, parent):
super(MyItem, self).__init__(name, parent)
def runtest(self):
if not MyItem.SUCCEEDED:
MyItem.SUCCEEDED = True
print "good job, buddy"
return
else:
print "you sucker, buddy"
raise Exception()
def repr_failure(self, excinfo):
return ""
您将在MyFile
和MyItem
类中生成/添加代码(而不是unittest.TestSuite
和unittest.TestCase
)。我保持MyFile
类的命名约定,因为它旨在表示您从文件中读取的内容,但当然您基本上可以将其解耦(正如我在此处所做的那样)。有关其正式示例,请参阅here。唯一的限制是,在我写的方式中,foo
必须作为文件存在,但您也可以将其解耦,例如:通过使用conftest.py
或树中存在的任何其他文件名(并且只有一次,否则所有匹配的文件都会运行 - 如果您不为每个文件执行if path.basename
测试树中存在的文件!!!)
您可以使用
从命令行运行此命令py.test -whatever -options
或使用
的任何代码编程import pytest
pytest.main("-whatever -options")
py.test的优点在于你可以解锁许多非常强大的插件,例如html report