pytest 是否有类似 google 测试的非致命 EXPECT_* 行为?

Does pytest have anything like google test's non-fatal EXPECT_* behavior?

我更熟悉 google 测试框架,了解它们支持的主要行为对 ASSERT_*EXPECT_*,即致命和非致命断言模式.

来自documentation

The assertions come in pairs that test the same thing but have different effects on the current function. ASSERT_* versions generate fatal failures when they fail, and abort the current function. EXPECT_* versions generate nonfatal failures, which don't abort the current function. Usually EXPECT_* are preferred, as they allow more than one failures to be reported in a test. However, you should use ASSERT_* if it doesn't make sense to continue when the assertion in question fails.

问题:pytest 是否也有我可以启用的非致命断言风格或模式?

最好允许全方位的测试最大限度地执行以获得最丰富的失败历史记录,而不是在第一次失败时中止,并可能隐藏必须由 运行 的多个实例分段发现的后续失败测试应用程序。

不,pytest 中没有这样的功能。最流行的方法是使用常规 assert 语句,如果表达式为假,则立即使测试失败。

It's nice to allow a full range of tests to maximally execute to get the richest failure history rather than abort at the first failure and potentially hide subsequent failures that have to be discovered piecewise by running multiple instances of the test application.

关于这是否好,众说纷纭。至少在开源 Python 社区中,流行的方法是:每个潜在的 "subsequent failure that is discovered piecewise" 都将在其自己的单独测试中编写。更多的测试,更小的测试,(理想情况下)只断言一件事。

您可以通过附加到错误列表然后在测试结束时断言列表为空来轻松地重新创建 EXPECT_* 东西,但是 pytest 中不直接支持此类功能.

我使用 pytest-assume 进行非致命断言。它做得很好。

安装

像往常一样,

$ pip install pytest-assume

使用示例

import pytest


def test_spam():
    pytest.assume(True)
    pytest.assume(False)

    a, b = True, False
    pytest.assume(a == b)

    pytest.assume(1 == 0)
    pytest.assume(1 < 0)

    pytest.assume('')
    pytest.assume([])
    pytest.assume({})

如果你觉得写pytest.assume有点过分,就给import取个别名:

import pytest.assume as expect


def test_spam():
    expect(True)
    ...

运行 以上测试结果:

$ pytest -v
============================= test session starts ==============================
platform linux -- Python 3.6.5, pytest-3.6.0, py-1.5.3, pluggy-0.6.0 -- /data/gentoo64-prefix/u0_a82/projects/Whosebug/so-50630845
cachedir: .pytest_cache
rootdir: /data/gentoo64-prefix/u0_a82/projects/Whosebug/so-50630845, inifile:
plugins: assume-1.2
collecting ... collected 1 item

test_spam.py::test_spam FAILED                                            [100%]

=================================== FAILURES ===================================
__________________________________ test_spam ___________________________________
test_spam.py:6: AssumptionFailure
        pytest.assume(False)


test_spam.py:9: AssumptionFailure
        pytest.assume(a == b)


test_spam.py:11: AssumptionFailure
        pytest.assume(1 == 0)


test_spam.py:12: AssumptionFailure
        pytest.assume(1 < 0)


test_spam.py:13: AssumptionFailure
        pytest.assume('')


test_spam.py:14: AssumptionFailure
        pytest.assume([])


test_spam.py:14: AssumptionFailure
        pytest.assume([])


test_spam.py:15: AssumptionFailure
        pytest.assume({})

------------------------------------------------------------
Failed Assumptions: 7
=========================== 1 failed in 0.18 seconds ===========================