跳转到主要内容

一个pytest插件,允许每个测试函数有多个失败。

项目描述

pytest-check

一个pytest插件,允许每个测试函数有多个失败。


通常,测试函数会在第一个失败的 assert 处失败并停止运行。这对于大量的软件测试来说是完全正常的。然而,有时你可能想检查多个事物,并且你真的想了解每个检查的结果,即使其中一个失败了。

pytest-check 允许每个测试函数有多个失败的“检查”,这样你就可以看到出错的整个情况。

安装

从PyPI

$ pip install pytest-check

从conda (conda-forge)

$ conda install -c conda-forge pytest-check

示例

你可能想要多个检查的快速示例

import httpx
from pytest_check import check

def test_httpx_get():
    r = httpx.get('https://www.example.org/')
    # bail if bad status code
    assert r.status_code == 200
    # but if we get to here
    # then check everything else without stopping
    with check:
        assert r.is_redirect is False
    with check:
        assert r.encoding == 'utf-8'
    with check:
        assert 'Example Domain' in r.text

导入与fixture

上面的示例使用了导入:from pytest_check import check

您也可以不导入而将 check 作为fixture获取

def test_httpx_get(check):
    r = httpx.get('https://www.example.org/')
    ...
    with check:
        assert r.is_redirect == False
    ...

验证函数

check 也提供了一些常见检查的辅助函数。这些方法不需要在 with check: 块内部。

函数 含义 注意
equal(a, b, msg="") a == b
not_equal(a, b, msg="") a != b
is_(a, b, msg="") a is b
is_not(a, b, msg="") a is not b
is_true(x, msg="") bool(x) is True
is_false(x, msg="") bool(x) is False
is_none(x, msg="") x is None
is_not_none(x, msg="") x is not None
is_in(a, b, msg="") a in b
is_not_in(a, b, msg="") a 不在 b 中
is_instance(a, b, msg="") isinstance(a, b)
is_not_instance(a, b, msg="") not isinstance(a, b)
is_nan(x, msg="") math.isnan(x) math.isnan
is_not_nan(x, msg="") not math.isnan(x) math.isnan
almost_equal(a, b, rel=None, abs=None, msg="") a == pytest.approx(b, rel, abs) pytest.approx
not_almost_equal(a, b, rel=None, abs=None, msg="") a != pytest.approx(b, rel, abs) pytest.approx
greater(a, b, msg="") a > b
greater_equal(a, b, msg="") a >= b
less(a, b, msg="") a < b
less_equal(a, b, msg="") a <= b
between(b, a, c, msg="", ge=False, le=False) a < b < c
between_equal(b, a, c, msg="") a <= b <= c 等同于 between(b, a, c, msg, ge=True, le=True)
raises(expected_exception, *args, **kwargs) 引发指定的异常 类似于 pytest.raises
fail(msg) 记录失败

注意:这是一个相对常见的逻辑运算符列表。我不太愿意添加太多,因为很容易添加自己的。

httpx 示例可以用辅助函数重写

def test_httpx_get_with_helpers():
    r = httpx.get('https://www.example.org/')
    assert r.status_code == 200
    check.is_false(r.is_redirect)
    check.equal(r.encoding, 'utf-8')
    check.is_in('Example Domain', r.text)

您使用的是个人喜好。

定义自己的检查函数

使用 @check.check_func

@check.check_func 装饰器允许您将任何包含 assert 语句的测试辅助函数包装成非阻塞 assert 函数。

from pytest_check import check

@check.check_func
def is_four(a):
    assert a == 4

def test_all_four():
    is_four(1)
    is_four(2)
    is_four(3)
    is_four(4)

使用 check.fail()

使用 @check.check_func 可能是最简单的。然而,它确实在通过的情况下有一些开销,这可能会影响检查的大型循环。

如果您需要一些加速,请使用以下样式,并借助 check.fail()

from pytest_check import check

def is_four(a):
    __tracebackhide__ = True
    if a == 4:
        return True
    else: 
        check.fail(f"check {a} == 4")
        return False

def test_all_four():
  is_four(1)
  is_four(2)
  is_four(3)
  is_four(4)

将 raises 用作上下文管理器

raises 用作上下文管理器,类似于 pytest.raises。主要区别在于,如果没有引发正确的异常,则不会停止测试方法的执行。

from pytest_check import check

def test_raises():
    with check.raises(AssertionError):
        x = 3
        assert 1 < x < 4

伪堆栈跟踪

使用 check,测试可以在每个测试中有多处失败。如果我们为每次失败都包含完整的堆栈跟踪,则可能会产生大量的输出。为了使输出更简洁,pytest-check 实现了一个较短的版本,我们称之为伪堆栈跟踪。

例如,考虑这个测试

def test_example():
    a = 1
    b = 2
    c = [2, 4, 6]
    check.greater(a, b)
    check.less_equal(b, a)
    check.is_in(a, c, "Is 1 in the list")
    check.is_not_in(b, c, "make sure 2 isn't in list")

这将导致以下结果

=================================== FAILURES ===================================
_________________________________ test_example _________________________________
FAILURE:
assert 1 > 2
  test_check.py, line 14, in test_example() -> check.greater(a, b)
FAILURE:
assert 2 <= 1
  test_check.py, line 15, in test_example() -> check.less_equal(b, a)
FAILURE: Is 1 in the list
assert 1 in [2, 4, 6]
  test_check.py, line 16, in test_example() -> check.is_in(a, c, "Is 1 in the list")
FAILURE: make sure 2 isn't in list
assert 2 not in [2, 4, 6]
  test_check.py, line 17, in test_example() -> check.is_not_in(b, c, "make sure 2 isn't in list")
------------------------------------------------------------
Failed Checks: 4
=========================== 1 failed in 0.11 seconds ===========================

红色输出

失败也将是红色,除非您使用 pytests 的 --color=no 关闭它。

无输出

您可以使用 pytests 的 --tb=no 关闭失败报告。

失败时停止(maxfail 行为)

设置 -x--maxfail=1 将导致此插件在第一次失败检查后停止测试。

设置 -maxfail=2 或更大值将关闭此插件中的任何 maxfail 处理,并由 pytest 控制。

换句话说,maxfail 计数是针对测试的,而不是检查。例外情况是 1,我们希望在第一次失败检查时停止。

any_failures()

使用 any_failures() 来查看是否有任何失败。
一个用例是将检查块的条件设置为在先前的检查集中未失败

from pytest_check import check

def test_with_groups_of_checks():
    # always check these
    check.equal(1, 1)
    check.equal(2, 3)
    if not check.any_failures():
        # only check these if the above passed
        check.equal(1, 2)
        check.equal(2, 2)

加速

如果您有很多检查失败,则您的测试可能不会像您希望的那样快速运行。有几个方法可以加速。

  • --check-max-tb=5 - 每个测试只包含前 5 个失败的重构堆栈跟踪(其余不包含)。

    • 示例显示 5,但可以使用任何数字。
    • pytest-check 使用我称之为伪堆栈跟踪的自定义堆栈跟踪代码。
    • 这与正常的 assert 堆栈跟踪相比,在视觉上更短。
    • 内部,它使用内省,这可能很慢。
    • 允许有限的伪回溯数量可以显著提高效率。
    • 默认值为1。
      • 如果你想对所有失败进行伪回溯,请设置一个较大的数字,例如:1000。
  • --check-max-report=10 - 限制每个测试中报告的失败次数。

    • 示例中显示的是10,但可以使用任何数字。
    • 测试仍将报告失败的总数。
    • 默认值为无限制。
  • --check-max-fail=20 - 在此许多检查失败后停止测试。

    • 如果你的测试代码运行缓慢,并且你想提前退出,这将非常有用。
    • 默认值为无限制。
  • 这些中的任何一个都可以单独使用,也可以组合使用。

  • 建议

    • 保留默认设置,相当于--check-max-tb=1
    • 如果过多的输出令人烦恼,请设置--check-max-report=10或某个可接受的数字。

局部加速

上述标志是全局设置,适用于测试运行中的每个测试。

在本地,您可以按测试设置这些值。

examples/test_example_speedup_funcs.py

def test_max_tb():
    check.set_max_tb(2)
    for i in range(1, 11):
        check.equal(i, 100)

def test_max_report():
    check.set_max_report(5)
    for i in range(1, 11):
        check.equal(i, 100)

def test_max_fail():
    check.set_max_fail(5)
    for i in range(1, 11):
        check.equal(i, 100)

贡献

非常欢迎贡献。可以使用tox运行测试。测试覆盖率现在是100%。请确保保持100%。如果您有一个很棒的pull request并且需要帮助将覆盖率恢复到100%,请告诉我。

许可协议

根据MIT许可证分发,"pytest-check"是免费和开源软件。

问题

如果您遇到任何问题,请提交问题,并附上详细描述。

变更日志

changelog.md

项目详情


下载文件

下载适合您平台的文件。如果您不确定选择哪个,请了解更多关于安装包的信息。

源分布

pytest_check-2.4.1.tar.gz (28.9 kB 查看哈希值)

上传时间

构建分布

pytest_check-2.4.1-py3-none-any.whl (13.8 kB 查看哈希值)

上传时间 Python 3

支持者

AWS AWS 云计算和安全赞助商 Datadog Datadog 监控 Fastly Fastly CDN Google Google 下载分析 Microsoft Microsoft PSF 赞助商 Pingdom Pingdom 监控 Sentry Sentry 错误日志 StatusPage StatusPage 状态页面