I have recently merged DM-22199, which provides class and method decorators for tests to provide iteration. The intent is to make it simple to extend unit tests to cover more cases.
If you create the object being tested in the setUp
method, use the class decorator, lsst.utils.tests.classParameters
. It creates multiple classes with the parameters you provide. For example:
from lsst.utils.tests import classParameters
@classParameters(foo=[1, 2], bar=[3, 4])
class MyTestCase(unittest.TestCase):
def setUp(self):
self.fooBar = FooBar(self.foo, self.bar)
will generate two classes, as if you wrote:
class MyTestCase_1_3(unittest.TestCase):
foo = 1
bar = 3
def setUp(self):
self.fooBar = FooBar(self.foo, self.bar)
...
class MyTestCase_2_4(unittest.TestCase):
foo = 2
bar = 4
def setUp(self):
self.fooBar = FooBar(self.foo, self.bar)
...
Note that the parameter values are embedded in the class name, which allows identification of the particular class in the event of a test failure.
If you want to iterate over parameters for an individual test, use the method decorator, lsst.utils.tests.methodParameters
. It loops over the parameters, using subTest
to identify the parameter combination in the event of a failure. For example:
from lsst.utils.tests import methodParameters
class MyTestCase(unittest.TestCase):
@methodParameters(foo=[1, 2], bar=[3, 4])
def testSomething(self, foo, bar):
...
will run tests:
testSomething(foo=1, bar=3)
testSomething(foo=2, bar=4)
There’s also a lsst.utils.tests.debugger
function decorator that will drop you into pdb
when it catches an exception.