I am trying to find a way to use nose to run multiple test cases within a class but I need to do so where nose only creates one instance of that class. This class will test a network and the setup of the network takes a few minutes thus the need to run all of the tests via one instance of the class. Here is a basic example of what I am trying to do:
class TestUmbrella(object):
def __init__(self):
log.info('__init__ called')
def run_A(self):
log.info('Test A is running')
def run_B(self):
log.info('Test B is running')
def run_C(self):
log.info('Test C is running')
def run_test(self):
for x in (self.run_A, self.run_B, self.run_C):
yield x
This produces:
2015-03-19 12:22:31,330: INFO: tests.l3.FooTest2: __init__ called
2015-03-19 12:22:31,331: INFO: tests.l3.FooTest2: __init__ called
2015-03-19 12:22:31,331: INFO: tests.l3.FooTest2: Test A is running
.2015-03-19 12:22:31,331: INFO: tests.l3.FooTest2: __init__ called
2015-03-19 12:22:31,332: INFO: tests.l3.FooTest2: Test B is running
.2015-03-19 12:22:31,332: INFO: tests.l3.FooTest2: __init__ called
2015-03-19 12:22:31,332: INFO: tests.l3.FooTest2: Test C is running
.
----------------------------------------------------------------------
Ran 3 tests in 0.002s
OK
What I would like to see is:
2015-03-19 12:22:31,330: INFO: tests.l3.FooTest2: __init__ called
2015-03-19 12:22:31,331: INFO: tests.l3.FooTest2: Test A is running
2015-03-19 12:22:31,332: INFO: tests.l3.FooTest2: Test B is running
2015-03-19 12:22:31,332: INFO: tests.l3.FooTest2: Test C is running
Any ideas on how to get nose to do this?
Two ways to get what you want: Use unittest.TestCase class with setUpClass for your TestUmbrella:
from unittest import TestCase
import logging as log
class TestUmbrella(TestCase):
@classmethod
def setUpClass(cls):
log.info('__init__ called')
def run_A_test(self):
log.info('Test A is running')
def run_B_test(self):
log.info('Test B is running')
def run_C_test(self):
log.info('Test C is running')
Note that you will no longer be able yield things on the fly, and would have to rename methods to comply with nose test pattern. That will give you:
$ nosetests cls_test.py -v
INFO:root:__init__ called
run_A_test (cls_test.TestUmbrella) ... INFO:root:Test A is running
ok
run_B_test (cls_test.TestUmbrella) ... INFO:root:Test B is running
ok
run_C_test (cls_test.TestUmbrella) ... INFO:root:Test C is running
ok
----------------------------------------------------------------------
Ran 3 tests in 0.007s
OK
Alternatively, you can just inject your setup method into the class, but not as part of class initialization:
import logging as log
class TestUmbrella(object):
def my_setup(self):
log.info('__init__ called')
def run_A(self):
log.info('Test A is running')
def run_B(self):
log.info('Test B is running')
def run_C(self):
log.info('Test C is running')
def run_test(self):
self.my_setup()
for x in (self.run_A, self.run_B, self.run_C):
yield x
Finally, if you really cannot offload heavy logic from the constructor, you can run your tests from a standalone function like this:
def run_test():
tu = TestUmbrella()
for x in (tu.run_A, tu.run_B, tu.run_C):
yield x