如何对装饰器分配给多个函数进行pytest

How to pytest that a decorator is assigned to multiple functions

我在 SO 的某处读到,您不应该测试装饰器,而应该测试包装函数的功能。然而,可能有更短的方法来测试某个装饰器是否被分配给多个函数。

我有这个装饰器:

def check_user(func):
    """Only allow admins to change the user_id in the annotated function.

    Use as decorator: @check_user
    """

    @wraps(func)
    def wrapper(*args, **kwargs):
    ...

我有一些测试来测试装饰器函数本身,例如:

def test_check_user(self):
    """Test the check user decorator if a non admin wants to overwrite the user."""
    with pytest.raises(ValueError) as ex:

        @check_user
        def foo(login: str, userId: str):
            return True

        foo(login="Foo", userId="Bar")

    assert ex.value.args[0] == "Only admin users may overwrite the userId."

现在我有大约 20 个 FastAPI 端点,我在其中分配了这个装饰器。 我想避免为每个函数重复相同的测试(参见上面的示例和其他测试)。 所以像这样的东西会很棒:

@pytest.mark.parametrize("method", ["foo", "bar", "gaga", ....])
def test_decorated_methods(self, method):
    assert assigned(check_user, method)  # or so

您应该能够参数化 test_check_user 以在一次测试中为每个修饰函数检查相同的断言。这优于仅检查是否应用了装饰器,因为它验证了防止非管理员更改 userId.

的实际功能要求

记住编写好的测试的目的是保护你免受未来的自我影响。虽然您目前觉得可以从这个装饰器的存在推断出安全特性,但您能确定这个推断在项目的剩余生命周期中始终为真吗?最好确保您的安全功能确实按预期运行。

@pytest.mark.parametrize("method,args,kwargs", [(my_func, ["Foo"], {}),
                                                (my_other_func, ["bar"], {})])
def test_cant_change_id_if_not_admin(func, args, kwargs):
    kwargs["userId"]="Bar"
    with pytest.raises(ValueError) as ex:
        func(*args, **kwargs)
    assert ex.value.args[0] == "Only admin users may overwrite the userId."