Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python nose test inheritance: load unit test fixtures from subclasses

I'm converting the test suite of a Python project from unittest to nose. The project's existing framework (based on unittest) is rather clunky, containing lots of heavily customised code for test discovery and running, so I'm trying to migrate to nose to make everything more streamlined.

I'm facing problems with the code that's generating test suites, however.

The project's framework has two ways of running tests. One is

class TestSomething(unittest.TestCase):

    def setUp(self):
        ...

    def test_x(self):
        ...

    def test_y(self):
        ...

suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestSomething))

which is the "straightforward" way, it's what all Nose examples and tutorials show, and it works. However, the second way is by defining a test class that contains all the test logic, then creating test cases in various subclasses that contain different setup configurations and inherit the tests from the superclass:

class TestSomething(unittest.TestCase):

    def test_x(self):
        ...

    def test_y(self):
        ...

class TestCase1(TestSomething):

    def setUp(self):
        ...

class TestCase2(TestSomething):

    def setUp(self):
        ...

suite = unittest.TestSuite()

cases = [TestCase1,TestCase2]
suite.addTests([unittest.makeSuite(case) for case in cases])

This is what Nose fails with. It tries to run the test methods first, which obviously doesn't work because there is no setUp() in the superclass and many of the variables used in test_x() and test_y() have not yet been defined.

I haven't found any examples of this done anywhere, and Nose's (rather sparse and difficult to navigate) documentation doesn't seem to mention it either. How can this be made to work with nose? Any help will be greatly appreciated.

like image 498
Boris Avatar asked Feb 18 '13 02:02

Boris


1 Answers

First of all, as unutbu noted, you shouldn't give to TestSomething a name that starts with Test, because nose automatically treats such classes as test-cases. Also, nose runs all TestCase subclasses he finds, thus doing:

class Something(unittest.TestCase):
    ...

gives exactly the same results you are having. I think you should not inherit from TestCase and use that class as a mix-in:

class Something(object):
    def test_x(self):
        # here the various assertEqual etc. do not resolve, but you can use them
        # as if they were present, since in real test-cases they will be inherited
        # from unittest.TestCase.
        ...
    ...

class TestCase1(unittest.TestCase, Something):
    def setUp(self):
        ...

An other way to do this is to set the class's __test__ attribute to False:

class TestSomething(unittest.TestCase):
    __test__ = False
    def test_x(self):
        ...


class TestCase1(TestSomething):
    __test__ = True  #must put this
    def setUp(self):
        ...

Alternatively you can use nose.istest and nose.nottest to mark which class is a testcase and which one isn't:

@tools.nottest
class TestSomething(unittest.TestCase):
    def test_x(self):
        ...

@tools.istest
class TestCase1(TestSomething):
    sef setUp(self):
        ...
like image 153
Bakuriu Avatar answered Nov 13 '22 19:11

Bakuriu