【发布时间】:2014-01-09 20:59:59
【问题描述】:
现在,我有一个 Python 包(我们称之为 mypackage),其中包含我使用 pytest 运行的一堆测试。一个特定的功能可以有许多可能的实现,因此我使用 funcarg 机制通过参考实现来运行这些测试。
# In mypackage/tests/conftest.py
def pytest_funcarg__Feature(request):
return mypackage.ReferenceImplementation
# In mypackage/tests/test_stuff.py
def test_something(Feature):
assert Feature(1).works
现在,我正在创建一个单独的 Python 包,它具有更高级的实现 (fancypackage)。 是否可以运行 mypackage 中包含 Feature funcarg 的所有测试,仅使用不同的实现?
如果我在mypackage 中添加新测试,我希望避免更改fancypackage,因此显式导入并不理想。我知道我可以使用pytest.main() 运行所有测试,但由于我的功能有多个实现,我不想多次调用pytest.main()。理想情况下,它看起来像这样:
# In fancypackage/tests/test_impl1.py
def pytest_funcarg__Feature(request):
return fancypackage.Implementation1
## XXX: Do pytest collection on mypackage.tests, but don't run them
# In fancypackage/tests/test_impl2.py
def pytest_funcarg__Feature(request):
return fancypackage.Implementation2
## XXX: Do pytest collection on mypackage.tests, but don't run them
然后,当我在 fancypackage 中运行 pytest 时,它会收集每个 mypackage.tests 测试两次,每个功能实现一次。我已经尝试使用显式导入来执行此操作,它似乎工作正常,但我不想显式导入所有内容。
奖金
另一个不错的好处是只收集那些包含Feature funcarg 的测试。这可能吗?
单元测试示例
在切换到 py.test 之前,我使用标准库的 unittest 进行了此操作。其功能如下:
def mypackage_test_suite(Feature):
loader = unittest.TestLoader()
suite = unittest.TestSuite()
mypackage_tests = loader.discover('mypackage.tests')
for test in all_testcases(mypackage_tests):
if hasattr(test, 'Feature'):
test.Feature = Feature
suite.addTest(test)
return suite
def all_testcases(test_suite_or_case):
try:
suite = iter(test_suite_or_case)
except TypeError:
yield test_suite_or_case
else:
for test in suite:
for subtest in all_testcases(test):
yield subtest
显然现在情况有所不同,因为我们正在处理测试函数和类而不仅仅是类,但似乎 py.test 中应该有一些等效的东西来构建测试套件并允许您迭代它。
【问题讨论】:
-
嗨@tbekolay,几年后回头看,您知道有什么好的解决方案可以解决您的问题吗?
-
我们最终在上游项目中创建了一个自定义plugin,然后在下游项目中使用
--pyargs upstream运行测试,由于conftest.py中设置的内容,运行上游测试与下游类。