Marco Selvi
Marco Selvi

Reputation: 171

Nosetests not seeing test classes that unittest discover does

I have what I can only consider a very odd problem with the way nosetests identifies classes that are valid tests classes.

I'm initialising a test class as a generic type with specific inheritance from a base tests class by using:

def random_test_class(n):
    print "Generating %d random test cases..." % n
    def make_test(genre, ss, ps):
        return lambda self: self.compose(genre, ss, ps)
    return type('TestEverything', (TestBase,),
                { 'test_%d' % i: make_test(genre, ss, ps)
                  for (i, (genre, ss, ps)) in zip(xrange(n), generate_settings())
                })

and then initialising the class proper with

class TestEverything(random_test_class(100)):
    pass

Now, when I call my standard testing framework with python -m unittest discover, the testing is all very happy and it sees the TestEverything class as a test class defining 100 test methods (test_1, test_2, etc...). However, if I use nosetests ./ -m "test_*" it refuses to see TestEverything as a valid test class, and doesn't run any of its test methods.

How can I solve this? I really need the xunit output framework that nosetests provide, but I would very much like to avoid going through all the metaclass faff that is required to properly initialise a class with a specific test metaclass.

Upvotes: 0

Views: 203

Answers (1)

Louis
Louis

Reputation: 151380

When deciding whether or not to include methods in tests, Nose checks the name of the function that implements the method rather than the attribute name. Change you make_test so that the test created has a name that Nose will pick up.

def make_test(genre, ss, ps):
    def test(self):
        self.compose(genre, ss, ps)
    return test

This will match the regular expression you give in your question. test_* matches any name that has test in it followed by any number of underscores.

Note that if you wanted the functions to have different names you could pass the index to make_test and set test.__name__:

def make_test(i, genre, ss, ps):
    def test(self):
        self.compose(genre, ss, ps)
    test.__name__ = 'test_%d' % i
    return test

Upvotes: 1

Related Questions