pytest 是不是有类似谷歌测试的非致命 EXPECT_* 行为?

Posted

技术标签:

【中文标题】pytest 是不是有类似谷歌测试的非致命 EXPECT_* 行为?【英文标题】:Does pytest have anything like google test's non-fatal EXPECT_* behavior?pytest 是否有类似谷歌测试的非致命 EXPECT_* 行为? 【发布时间】:2018-05-31 18:44:42 【问题描述】:

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

来自documentation:

断言成对出现,测试相同的东西,但有 对当前功能的不同影响。 ASSERT_* 版本生成 失败时的致命失败,并中止当前功能。 EXPECT_* 版本生成非致命故障,不会中止 当前功能。通常 EXPECT_* 是首选,因为它们允许更多 在测试中报告的失败不止一个。但是,您应该使用 ASSERT_* 如果在断言中继续没有意义 问题失败。

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

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

【问题讨论】:

【参考方案1】:

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

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

这好不好众说纷纭。至少在开源 Python 社区中,流行的方法是:每个潜在的“分段发现的后续故障”都将编写在其自己的单独测试中。更多的测试,更小的测试,(理想情况下)只断言一件事。

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

【讨论】:

【参考方案2】:

我将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/***/so-50630845
cachedir: .pytest_cache
rootdir: /data/gentoo64-prefix/u0_a82/projects/***/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 ===========================

【讨论】:

我见过import pytest.assumefrom pytest import assume,但这些都不适合我。我只是做了pip install pytest-assume。为什么要导入的包不称为pytest_assume,因此不是from pytest_assume import assume 或类似名称?这也不起作用。为什么这与所有其他 pip 包不同? pip 中是否有 pytest 插件支持?如果是这样,我如何刷新pytest 模块的世界观? @davidA 1. 只有在您使用pytest 实际运行测试时,导入才会起作用。这不是真正的导入,而是仅用于测试的模块猴子补丁。 2. 如果你已经安装了pytest-assume,从我的回答中复制了示例测试sn-p,当你运行pytest时导入失败,很可能是你本地设置的问题。通常,原因是安装了多个 Python 并使用 pip install 获取错误的解释器版本。 @davidA 要对此进行测试,请运行 python -c "import pytest_assume"。如果失败,运行pip -Vpython -V 并比较列出的解释器版本——很可能你安装了错误解释器的包。如果它有效,您还有另一个更严重的问题 - 最好为此提出一个单独的问题,提供有关您本地设置的更多详细信息。 啊,这就解释了——谢谢。我看到pytest在运行时检测到并列出了该插件,因此它安装正确。

以上是关于pytest 是不是有类似谷歌测试的非致命 EXPECT_* 行为?的主要内容,如果未能解决你的问题,请参考以下文章

为啥在使用 pytest-qt 进行测试时出现致命的 Python 错误?

使用 QT 运行 pytest 时出现致命的 Python 错误

如何使用 pytest 禁用测试?

如何在pytest下测试单个文件

致命错误:对 SQL SERVER 2012 的非对象 XAMPP 上的成员函数 query() 调用

pytest简介