24

Possible Duplicate:
How do you generate dynamic (parameterized) unit tests in Python?

Is there a way to dynamically create unittest test cases? I have tried the following...

class test_filenames(unittest.TestCase):

    def setUp(self):
        for category, testcases in files.items():
            for testindex, curtest in enumerate(testcases):
                def thetest():
                    parser = FileParser(curtest['input'])
                    theep = parser.parse()
                    self.assertEquals(theep.episodenumber, curtest['episodenumber'])

                setattr(self, 'test_%s_%02d' % (category, testindex), thetest)

..which creates all the methods correctly (they show up in dir() and are callable), but unittest's test detector, nor nosetest executes them ("Ran 0 tests in ...")

Since I may be asking the wrong question - what I am trying to achieve:

I have a file containing test data, a list of input filenames, and expected data (simplified to episodenumber in the above code), stored in a Python dictionary. The key is the category, the value is a list of test cases, for example...

test_cases = {}
test_cases['example_1'] = [
    {'input': 'test.01',
    'episodenumber': 1},
    {'input': 'test.02',
    'episodenumber': 2}
]

test_cases['example_2'] = [
    {'input': 'another.123',
    'episodenumber': 123},
    {'input': 'test.e42',
    'episodenumber': 32}
]

Currently I just loop over all the data, call self.assertEquals on each test. The problem is, if one fails, I don't see the rest of the failures as they are also grouped into one test, which aborts when an assertion fails.

The way around this, I thought, would be to (dynamically) create a function for each test case, perhaps there is a better way?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
dbr
  • 165,801
  • 69
  • 278
  • 343
  • Another possible duplicate is *[Python library 'unittest': Generate multiple tests programmatically](https://stackoverflow.com/questions/2798956)*. – Peter Mortensen Feb 05 '21 at 16:13

2 Answers2

25

In the following solution, the class Tests contains the helper method check and no test cases statically defined. Then, to dynamically add a test cases, I use setattr to define functions in the class. In the following example, I generate test cases test_<i>_<j> with i and j spanning [1,3] and [2,5] respectively, which use the helper method check with different values of i and j.

class Tests(unittest.TestCase):
    def check(self, i, j):
        self.assertNotEquals(0, i-j)



for i in xrange(1, 4):
    for j in xrange(2, 6):
        def ch(i, j):
            return lambda self: self.check(i, j)
        setattr(Tests, "test_%r_%r" % (i, j), ch(i, j))
Adrian Panasiuk
  • 7,249
  • 5
  • 33
  • 54
12

For this you should use test generators in nose. All you need to do is yield a tuple, with the first being a function and the rest being the args. From the docs here is the example.

def test_evens():
    for i in range(0, 5):
        yield check_even, i, i*3

def check_even(n, nn):
    assert n % 2 == 0 or nn % 2 == 0
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
David Raznick
  • 17,907
  • 2
  • 35
  • 27