Search code examples
pythonunit-testingnosenose2

Skip a unit test from a Nose2 Plugin


I'm having trouble actually skipping a unit test from a Nose2 plugin. I am able to mark the test skipped and see the reason in the final result, but the test still runs. This example code should basically skip any test, as long as the plugin is active.

from nose2.events import Plugin

class SkipAllTests(Plugin):
    def startTest(self, event):
        event.result.addSkip(event.test, 'skip it')
        event.handled = True

If I call event.test.skipTest('reason') it actually raises the SkipTest exception like it should, it's just that the exception isn't caught by the test runner, it just raises inside of my startTest hook method. Any ideas?


Solution

  • I don't think you can actually stop a test from running with the startTest hook. The nose2 docs suggest using either matchPath or getTestCaseNames to do this. Here's a working example using matchPath:

    from nose2.events import Plugin
    
    class SkipAllTests(Plugin):
        configSection = "skipper"
        commandLineSwitch = (None, 'skipper', "Skip all tests")
    
        def matchPath(self, event):
            event.handled = True
            return False
    

    The matchPath docs actually explictly explain how it can be used to stop tests from running:

    Plugins can use this hook to prevent python modules from being loaded by the test loader or force them to be loaded by the test loader. Set event.handled to True and return False to cause the loader to skip the module.

    Using this method will prevent the test case from ever being loaded. If you want the test to actually show up in the list as skipped, rather than not have it show up in the list of tests at all, you can do a little bit of hackery with the StartTestEvent:

    def dummy(*args, **kwargs):
        pass
    
    class SkipAllTests(Plugin):
        configSection = "skipper"
        commandLineSwitch = (None, 'skipper', "Skip all tests")
        def startTest(self, event):
            event.test._testFunc = dummy
            event.result.addSkip(event.test, 'skip it')
            event.handled = True
    

    Here, we replace the actual function the test is going to run with a dummy function that does nothing. That way, when the test executes, it no-ops, and then reports that it was skipped.