Skip unittest test without decorator syntax

后端 未结 4 400
野的像风
野的像风 2021-02-02 14:05

I have a suite of tests that I have loaded using TestLoader\'s (from the unittest module) loadTestsFromModule() method, i.e.,

suite = loader.loadTestsFromModule         


        
相关标签:
4条回答
  • 2021-02-02 14:06

    Google brought me here.

    I found the easiest way to do this is by raising a SkipTest exception when your skip criteria is met.

    from unittest.case import SkipTest
    
    def test_this_foo(self):
        if <skip conditsion>:
            raise SkipTest
    

    And that test will be marked as skipped.

    0 讨论(0)
  • 2021-02-02 14:09

    Using unittest.TestCase.skipTest:

    import unittest
    
    class TestFoo(unittest.TestCase):
        def setUp(self): print('setup')
        def tearDown(self): print('teardown')
        def test_spam(self): pass
        def test_egg(self): pass
        def test_ham(self): pass
    
    if __name__ == '__main__':
        import sys
        loader = unittest.loader.defaultTestLoader
        runner = unittest.TextTestRunner(verbosity=2)
        suite = loader.loadTestsFromModule(sys.modules['__main__'])
        for ts in suite:
            for t in ts:
                if t.id().endswith('am'): # To skip `test_spam` and `test_ham`
                    setattr(t, 'setUp', lambda: t.skipTest('criteria'))
        runner.run(suite)
    

    prints

    test_egg (__main__.TestFoo) ... setup
    teardown
    ok
    test_ham (__main__.TestFoo) ... skipped 'criteria'
    test_spam (__main__.TestFoo) ... skipped 'criteria'
    
    ----------------------------------------------------------------------
    Ran 3 tests in 0.001s
    
    OK (skipped=2)
    
    
    ----------------------------------------------------------------------
    Ran 3 tests in 0.002s
    
    OK (skipped=2)
    

    UPDATE

    Updated the code to patch setUp instead of test method. Otherwise, setUp/tearDown methods will be executed for test to be skipped.

    NOTE

    unittest.TestCase.skipTest (Test skipping) was introduced in Python 2.7, 3.1. So this method only work in Python 2.7+, 3.1+.

    0 讨论(0)
  • 2021-02-02 14:18

    This is a bit of a hack, but because you only need to raise unittest.SkipTest you can walk through your suite and modify each test to raise it for you instead of running the actual test code:

    import unittest
    from unittest import SkipTest
    
    class MyTestCase(unittest.TestCase):
        def test_this_should_skip(self):
            pass
    
        def test_this_should_get_skipped_too(self):
            pass
    
    def _skip_test(reason):
        raise SkipTest(reason)
    
    if __name__ == '__main__':
        suite = unittest.TestLoader().loadTestsFromTestCase(MyTestCase)
        for test in suite:
            skipped_test_method = lambda: _skip_test("reason")
            setattr(test, test._testMethodName, skipped_test_method)
        unittest.TextTestRunner(verbosity=2).run(suite)
    

    When I run this, this is the output I get:

    test_this_should_get_skipped_too (__main__.MyTestCase) ... skipped 'reason'
    test_this_should_skip (__main__.MyTestCase) ... skipped 'reason'
    
    ----------------------------------------------------------------------
    Ran 2 tests in 0.000s
    
    OK (skipped=2)
    
    0 讨论(0)
  • 2021-02-02 14:32

    Some observations:

    • A test is a callable object with a __call__(result) method
    • TestCase provides a higher-level interface, allowing test methods to throw a SkipTest exception to skip themselves
    • The skip decorators do exactly this
    • Skipped tests are recorded calling the TestResult.addSkip(test, reason) method.

    So you just need to replace the to-be-skipped tests with a custom test that calls addSkip:

    class Skipper(object):
        def __init__(self, test, reason):
            self.test = test
            self.reason = reason
    
        def __call__(self, result):
            result.addSkip(self.test, self.reason)
    
    0 讨论(0)
提交回复
热议问题