如何配置pytest以避免因丢失的导入而导致收集失败?

时间:2019-07-11 20:53:42

标签: python pytest

我确实有一些更复杂的项目,如果您运行pytest --collect-only,您将最终因发现的测试文件导致导入失败而导致导入失败。

我想更改这些测试文件,以使其在收集时不会失败。

这是因为用户可能希望使用pytest -k foo之类的特定模式运行测试,但是如果不相关的测试收集失败,他将无法执行此操作。

我知道我可以定义一个pytest_configure方法,该方法称为durind集合,但是如果我将导入移入其中,那么当解释器到达尝试使用缺少的导入的代码时,仍然会失败。 / p>

def pytest_configure(config):
    try:
        import foo
    except:
        pytest.skip("skipping when foo is not installed")

def test_foo()
  assert foo.is_enabled()  # <-- foo is undefined here

我的示例显然过度仿真,因为我们都知道我可以在测试方法中再次添加导入,但是我不想在数十种方法中这样做。我正在寻找更清洁的解决方案。

1 个答案:

答案 0 :(得分:1)

如果您不想因导入(或任何其他)错误而中止测试集合,请使用--continue-on-collection-errors标志。示例:

test_spam.py的导入未解决:

import foo


def test_foo():
    assert foo.is_enabled()

test_eggs.py是可运行的:

def test_bar():
    assert True

运行测试会得到:

$ pytest --continue-on-collection-errors -v
======================================= test session starts =======================================
...
collected 1 item / 1 errors                                                                       

test_eggs.py::test_bar PASSED

============================================= ERRORS ==============================================
__________________________________ ERROR collecting test_spam.py __________________________________
ImportError while importing test module '/home/hoefling/projects/private/stackoverflow/so-56997157/test_spam.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
test_spam.py:2: in <module>
    import foo
E   ModuleNotFoundError: No module named 'foo'
================================ 1 passed, 1 error in 0.06 seconds ================================

这将指示pytest运行它可以收集的所有测试(在此示例中为test_eggs::test_bar),但是由于无法收集一个模块而使执行失败。如果您不想失败,请使用pytest提供便捷的importorskip函数:

import pytest
foo = pytest.importorskip('foo')


def test_foo():
    assert foo.is_enabled()

现在运行测试将产生:

$ pytest -v
======================================= test session starts =======================================
...
collected 1 item / 1 skipped                                                                      

test_eggs.py::test_bar PASSED                                                               [100%]

=============================== 1 passed, 1 skipped in 0.04 seconds ===============================

如您所见,这两者之间的区别在于对收集错误的处理(1 errors1 skipped)以及最终的退出代码(1与0)。


就我个人而言,我倾向于不使用importorskip,因为它可能导致长期不执行测试。如果您有大型测试套件,通常只需简要查看测试结果(失败/未失败),而不必显式检查是否有新的跳过的测试。这可能导致以下情况:测试没有在任何地方(甚至没有在CI服务器上)执行,直到有人注意到它(最佳情况),或者(最坏情况)假设被测试的代码在生产系统上显示错误。当然,还有其他一些指标可以间接地保护该情况(例如,注意测试范围并禁止降低测试范围的提交),但是IMO的显式失败设置了一个巨大的感叹号,您无法避免。 >

来源:Skipping on a missing import dependency