Skip to main content
 首页 » 编程设计

python之pytest 参数化装饰器不适用于 **kwargs

2025年05月04日20qlqwjy

在我的测试代码中,我有以下内容:

@pytest.mark.parametrize(("title", "description", 'site'), [ 
                        ("abc", "this is a proper description","minecraft.net"), 
                        ("proper title","short","minecraft.net"), 
                        ("proper title", "this is a proper description","bol"), 
                        ("","this is a proper description","minecraft.net"), 
                        ("proper title","","minecraft.net"), 
                        ("proper title","this is a proper description",""), 
                        ("proper title","this is a proper description","ftp://myftp.nl") 
        ]) 
@ae_test(loggedin = True) 
def test_mod_model_create_validation(title, description,site): 
    ... testing code .... 

因此,parameterize 函数尝试参数化由我自己的 @ae_test 装饰器返回的函数,它看起来像这样:

def ae_test(prob=1.00,loggedin=False,is_admin=False): 
    def create_wrapper(func): 
        def run_test(*args,**kwargs): 
            ... test setup code ... 
            func(*args,**kwargs) 
            ... test teardown code ... 

到目前为止,这对我的所有测试都有效,但参数化函数有问题:

ValueError: <function run_test at 0x1029b55f0> has no argument 'title' 

这个错误出现在pytest/python.py的第638行

为了回应第一条评论,这里是完整的堆栈跟踪:

==================================== ERRORS ==================================== 
___________________ ERROR collecting test_content_models.py ____________________ 
/Library/Python/2.7/site-packages/pytest-2.2.4-py2.7.egg/_pytest/runner.py:120: in __init__ 
>               self.result = func() 
/Library/Python/2.7/site-packages/pytest-2.2.4-py2.7.egg/_pytest/main.py:304: in _memocollect 
>       return self._memoizedcall('_collected', lambda: list(self.collect())) 
/Library/Python/2.7/site-packages/pytest-2.2.4-py2.7.egg/_pytest/main.py:228: in _memoizedcall 
>           res = function() 
/Library/Python/2.7/site-packages/pytest-2.2.4-py2.7.egg/_pytest/main.py:304: in <lambda> 
>   return self._memoizedcall('_collected', lambda: list(self.collect())) 
/Library/Python/2.7/site-packages/pytest-2.2.4-py2.7.egg/_pytest/python.py:207: in collect 
>                   res = self.makeitem(name, obj) 
/Library/Python/2.7/site-packages/pytest-2.2.4-py2.7.egg/_pytest/python.py:218: in makeitem 
>           collector=self, name=name, obj=obj) 
/Library/Python/2.7/site-packages/pytest-2.2.4-py2.7.egg/_pytest/main.py:141: in call_matching_hooks 
>       return hookmethod.pcall(plugins, **kwargs) 
/Library/Python/2.7/site-packages/pytest-2.2.4-py2.7.egg/_pytest/core.py:425: in pcall 
>       return self._docall(methods, kwargs) 
/Library/Python/2.7/site-packages/pytest-2.2.4-py2.7.egg/_pytest/core.py:432: in _docall 
>           res = mc.execute() 
/Library/Python/2.7/site-packages/pytest-2.2.4-py2.7.egg/_pytest/core.py:350: in execute 
>           res = method(**kwargs) 
/Library/Python/2.7/site-packages/pytest-2.2.4-py2.7.egg/_pytest/python.py:103: in pytest_pycollect_makeitem 
>               return collector._genfunctions(name, obj) 
/Library/Python/2.7/site-packages/pytest-2.2.4-py2.7.egg/_pytest/python.py:232: in _genfunctions 
>       gentesthook.pcall(plugins, metafunc=metafunc) 
/Library/Python/2.7/site-packages/pytest-2.2.4-py2.7.egg/_pytest/core.py:425: in pcall 
>       return self._docall(methods, kwargs) 
/Library/Python/2.7/site-packages/pytest-2.2.4-py2.7.egg/_pytest/core.py:432: in _docall 
>           res = mc.execute() 
/Library/Python/2.7/site-packages/pytest-2.2.4-py2.7.egg/_pytest/core.py:350: in execute 
>           res = method(**kwargs) 
/Library/Python/2.7/site-packages/pytest-2.2.4-py2.7.egg/_pytest/python.py:37: in pytest_generate_tests 
>           metafunc.parametrize(*p.args, **p.kwargs) 
/Library/Python/2.7/site-packages/pytest-2.2.4-py2.7.egg/_pytest/python.py:638: in parametrize 
>                   raise ValueError("%r has no argument %r" %(self.function, arg)) 
E                   ValueError: <function run_test at 0x1029b55f0> has no argument 'title' 
=========================== 1 error in 0.36 seconds ============================ 

但问题实际上归结为 parameterize 寻找名为“title”的参数但没有找到它。那是因为我使用的是 **kw 语法。我希望 parameterize 函数只是将一个字典放在那里。

请您参考如下方法:

您最好使用 decorator.decorator decorator 装饰器将您的 ae_test 装饰器转换为保留签名的装饰器:

from decorator import decorator 
 
def ae_test(prob=1.00,loggedin=False,is_admin=False): 
    @decorator 
    def run_test(func, *args, **kwargs): 
        ... test setup code ... 
        func(*args,**kwargs) 
        ... test teardown code ... 
    return run_test