Corey Coogan
Corey Coogan

Reputation: 1639

Nose ignores test with custom decorator

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

Upvotes: 25

Views: 4256

Answers (1)

madjar
madjar

Reputation: 12961

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.

Upvotes: 24

Related Questions