【问题标题】:Running pytest tests in another Python package在另一个 Python 包中运行 pytest 测试
【发布时间】: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 中设置的内容,运行上游测试与下游类。

标签: python pytest


【解决方案1】:

您可以参数化您的 Feature 夹具:

@pytest.fixture(params=['ref', 'fancy'])
def Feature(request):
    if request.param == 'ref':
        return mypackage.ReferenceImplementation
    else:
        return fancypackage.Implementation1

现在,如果您运行 py.test,它将同时测试两者。

在他们使用的夹具上选择测试是不可能的 AFAIK,您可能可以使用 request.applymarker()-m 拼凑一些东西。但是。

【讨论】:

  • 理想情况下,fancypackage 不会运行参考实现测试,但是如果我至少可以从 mypackage 加载一次所有测试,那么参数化该功能可能很有用。我已经用unittestsn-p 更新了这个问题,它可以满足我的需求,以防万一。
  • 一种告诉 pytest “给我从这里开始的所有测试的集合”然后“将它们添加到我的测试集合”的方法将是一个不错的功能。制定确切的 UI 和实现是一些工作,但肯定是可行的,可能通过添加一个新的钩子。
  • 我很乐意帮助实现该功能@hpk42!我创建了一个issue 来讨论这个想法和 UI。
  • 另一种可能现在起作用的可能性是添加一个命令行选项来选择哪个夹具并在命令行选项禁用它时在夹具中提高pytest.Skip。这样你就可以使用参数化并且只对一个夹具执行测试。
  • 以上链接问题移至:github.com/pytest-dev/pytest/issues/421
猜你喜欢
  • 1970-01-01
  • 2013-02-26
  • 2020-04-25
  • 2020-06-14
  • 2019-11-04
  • 2017-04-04
  • 2018-01-25
  • 2018-06-01
  • 1970-01-01
相关资源
最近更新 更多