如何告知pytest某个函数失败的断言是正确行为?

0 投票
1 回答
20 浏览
提问于 2025-04-12 13:16

背景:在我的一个项目中,我使用了pytest,并且有一个辅助函数,这个函数在很多测试中负责最后的断言。所以代码大概是这样的:

tsthelper.py:

def check(obj1, obj2, *args):
    # do stuff calculate (using args) from the objects two strings str1 and str2
    assert str1 == str2

test_arg1.py:

from tsthelper import check

def test_arg1_():
    # Setup obj1 and obj2
    check(obj1, obj2, arg1):

def test_arg2_():
    # Setup obj1 and obj2
    check(obj1, obj2, arg2):
...

def test_no_arg1_should_fail():
    # Setup obj1 and obj2
    check(obj1, obj2):

所以,大部分函数应该是用来进行断言的,只有最后一个应该失败。

我觉得使用xfail这个功能并不是个好主意,因为这样的话,pytest会把失败的情况单独计算。但我想要的是,最后一个函数的失败被视为正确的行为,这样pytest在统计时应该把它算作成功。

我需要给这个失败的函数加上什么装饰器,才能让它被当作成功处理呢?

1 个回答

0

不同的函数专门测试不同的行为,这样做的目的是为了让调试变得更简单,测试覆盖面更广,而且在使用测试驱动开发(TDD)时更灵活。

如果你想让某个测试中的 check() 断言失败,可以试试在测试里使用 pytest.raises


import pytest
from tsthelper import check

def test_no_arg1_should_fail():
    # Setup obj1 and obj2
    with pytest.raises(AssertionError):
        check(obj1, obj2)

这样,当 check() 方法抛出一个断言异常时,测试函数就会把这个当作正确的行为,从而通过测试。

更好的方法

下面是一些更符合 Python 风格的替代方案,可以让你的测试保持干净且易于理解。

  • 修改 check() 函数,只返回 str1 是否等于 str2 的结果,然后每个测试函数明确地断言 check() 的结果是 True 还是 False。
def check(obj1, obj2, *args):
    return str1 == str2

def my_test():
    results = check(obj1, obj2, arg2)
    assert True == results
  • 使用 pytest 参数化: 从你分享的代码来看,你是在用不同的参数测试同一个函数。一个很好的方法是使用 pytest 参数化,这样可以遵循 DRY 原则,避免重复代码。

没有参数化的代码

def check_add(a,b):
    return a + b

def test_positive_numbers():
    assert check_add(3, 2) == 5

def test_negative_numbers():
    assert check_add(-2, -2) == -4

def test_zero():
    assert check_add(0, 0) == 0

使用参数化的代码

@pytest.mark.parametrize("a, b, expected", [
    (3, 2, 5),
    (-2, -2, -4),
    (0, 0, 0),
])
def test_ints(a, b, expected):
    assert check_add(a, b) == expected

这样做基本上会对所有不同的输入运行你的函数,作为不同的测试,从而减少代码重复。

你可以在 这里 了解更多信息。

撰写回答