How do I skip a whole Python unittest module at run-time?
After looking at the other answers here, this is the best answer I've come up with. It's ugly, embedding the whole test suite in the exception handling, but it appears to do what you want. Specifically skipping the tests when the imports don't work.
Assuming you're talking about using nosetests -x for running the tests it should carry on past the tests that skip, at least it appeared to when I tried it.
import unittest
try:
import PyQt4
# the rest of the imports
# actual tests go here.
class TestDataEntryMixin(unittest.TestCase):
def test_somefeature(self):
# ....
except ImportError, e:
if e.message.find('PyQt4') >= 0:
class TestMissingDependency(unittest.TestCase):
@unittest.skip('Missing dependency - ' + e.message)
def test_fail():
pass
else:
raise
if __name__ == '__main__':
unittest.main()
If the import fails it replaces the test run with a single test that simply skips. I've also attempted to make sure that it doesn't swallow any exceptions unintentionally. This solution owes a lot to all the other answers and comments to the question.
If you run it in verbose mode you will see this when it skips,
test_fail (test_openihm_gui_interface_mixins.TestMissingDependency) ... skipped 'Missing dependency - No module named PyQt4'
If you look at the definition of unittest.skipIf
and unittest.skip
, you can see that the key is doing raise unittest.SkipTest(reason)
when the test is executed. If you're okay with having it show up as one skipped test instead of several in the testrunner, you can simply raise unittest.SkipTest
yourself on import:
import unittest
try:
# do thing
except SomeException:
raise unittest.SkipTest("Such-and-such failed. Skipping all tests in foo.py")
Running with nosetests -v
gives:
Failure: SkipTest (Such-and-such failed. Skipping all tests in foo.py) ... SKIP:
Such-and-such failed. Skipping all tests in foo.py
----------------------------------------------------------------------
Ran 1 test in 0.002s
OK (SKIP=1)
@unittest.skip('comments_for_skipping_unit_tests')
class MyTests(unittest.TestCase):
def setUp(self):
pass
def test_something(self):
You can skip the whole unit test class by using the @unittest.skip decorator.
I found that using skipTest in setUp worked well. If you need a module imported, you use a try block to set e.g. module_failed = True, and in setUp call skipTest if it's set. This reports the correct number of test skips with only a short try block needed:
import unittest
try:
import my_module
module_failed = False
except ImportError:
module_failed = True
class MyTests(unittest.TestCase):
def setUp(self):
if module_failed:
self.skipTest('module not tested')
def test_something(self):
#...