Nose 忽略使用自定义装饰器的测试

发布于 2024-12-09 03:42:53 字数 978 浏览 0 评论 0原文

我的 Python 代码中有一些相对复杂的集成测试。我使用自定义装饰器极大地简化了它们,我对结果非常满意。这是我的装饰器的一个简单示例:

def specialTest(fn):

    def wrapTest(self):
        #do some some important stuff
        pass
    return wrapTest

测试可能如下所示:

class Test_special_stuff(unittest.TestCase):

    @specialTest
    def test_something_special(self):
        pass

这非常有效,并且由 PyCharm 的测试运行程序执行,没有任何问题。但是,当我使用 Nose 从命令行运行测试时,它会跳过使用 @specialTest 装饰器的任何测试。 我尝试将装饰器命名为 testSpecial,因此它符合默认规则,但随后我的 FN 参数未通过。

我怎样才能让 Nose 执行这些测试方法并按预期对待装饰器?


解决方案

感谢 madjar,我通过使用 functools.wraps 并更改包装器的名称将代码重组为如下所示,从而实现了此工作:

from functools import wraps

def specialTest(fn):

    @wraps(fn)
    def test_wrapper(self,*args,**kwargs):
        #do some some important stuff
        pass
    return test_wrapper


class Test_special_stuff(unittest.TestCase):

    @specialTest
    def test_something_special(self):
        pass

I have some relatively complex integration tests in my Python code. I simplified them greatly with a custom decorator and I'm really happy with the result. Here's a simple example of what my decorator looks like:

def specialTest(fn):

    def wrapTest(self):
        #do some some important stuff
        pass
    return wrapTest

Here's what a test may look like:

class Test_special_stuff(unittest.TestCase):

    @specialTest
    def test_something_special(self):
        pass

This works great and is executed by PyCharm's test runner without a problem. However, when I run a test from the commandline using Nose, it skips any test with the @specialTest decorator.
I have tried to name the decorator as testSpecial, so it matches default rules, but then my FN parameter doesn't get passed.

How can I get Nose to execute those test methods and treat the decorator as it is intended?


SOLUTION

Thanks to madjar, I got this working by restructuring my code to look like this, using functools.wraps and changing the name of the wrapper:

from functools import wraps

def specialTest(fn):

    @wraps(fn)
    def test_wrapper(self,*args,**kwargs):
        #do some some important stuff
        pass
    return test_wrapper


class Test_special_stuff(unittest.TestCase):

    @specialTest
    def test_something_special(self):
        pass

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

风启觞 2024-12-16 03:42:53

如果我没记错的话,nose 会根据它们的名称加载测试(名​​称以 test_ 开头的函数)。在您发布的代码片段中,您没有在包装函数中复制函数的 __name__ 属性,因此返回的函数的名称是 wrapTest 并且鼻子认为它不是测试。

将函数属性复制到新函数的一种简单方法是使用 functools.wraps

If I remember correctly, nose loads the test based on their names (functions whose name begins with test_). In the snippet you posted, you do not copy the __name__ attribute of the function in your wrapper function, so the name of the function returned is wrapTest and nose decides it's not a test.

An easy way to copy the attributes of the function to the new one is to used functools.wraps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文