python unittest 深刻failfast及实际应用【示例】

  1. failfast是TestResult的一个属性,缺省为False,python

  2. 做用: 若是failfast为True,一旦测试集中有测试案例failed或发生error当即终止当前整个测试执行,跳过剩下全部测试案例ide

  3. 各类用法:    实现“短路测试”,设置failfast为True测试

    1. unittest.main(failfast=True)ui

    2.  unittest.TextTestRunner(failfast=True)debug

    3. 设置TestResult控制,eg:unittest.TextResult.failfast=Truecode

      1. unittest.TestCase().run(result)utf-8

      2. unittest.TestSuite测试集实例ts,ts.run(result)rem

      3. override本身的测试案例类的run(self,testresult=None)方法,关键是设置testresult.failfast=True
        get

  4. 局限:unittest缺省实现控制整个测试集的“短路测试”,不能很好的知足基于测试案例类层面的控制it

  5. 问题场景:eg: 同一测试集下N个相对独立的业务流程测试案例testcaseclass(每一个包含n个步骤即testmethod)

    1. 指望每一个testcaseclass对应的独立流程一旦有一个步骤failed终止执行该流程测试案例剩下步骤

    2. 每一个testcaseclass的测试执行失败不影响其它同一测试集下的业务流程测试

    3. 但愿统一业务流程测试集testsuite加载、执行、不是单独一个一个testcasecalss的加载、运行

  6. 问题方案:我的发现unittest目前的实现不能很好的解决5.中问题场景,实现初步验证ok方案以下:

    1. 直接override的unittest.suite模块TestSuite的run(self,result)方法(修改几行代码)

    2. 修改点以下:#注释对应部分为我的添加修改部分

    def run(self, result, debug=False):
        topLevel = False
        if getattr(result, '_testRunEntered', False) is False:
            result._testRunEntered = topLevel = True

        for index, test in enumerate(self):
#             if result.shouldStop:
#                 break

            if _isnotsuite(test):
                self._tearDownPreviousClass(test, result)
                self._handleModuleFixture(test, result)
                self._handleClassSetUp(test, result)
#                 result._previousTestClass = test.__class__
                # begin: failfast on the testcaselevel
                if result._previousTestClass == test.__class__:
                    if  result.shouldStop:
                        continue
                else:                    
                    result._previousTestClass = test.__class__
                    if  result.shouldStop:
                           result.shouldStop = False
                # end 
                           
                if (getattr(test.__class__, '_classSetupFailed', False) or
                    getattr(result, '_moduleSetUpFailed', False)):
                    continue

            if not debug:
                test(result)
            else:
                test.debug()

            if self._cleanup:
                self._removeTestAtIndex(index)

        if topLevel:
            self._tearDownPreviousClass(None, result)
            self._handleModuleTearDown(result)
        return result

最好附上测试代码及执行结果:

# encoding: utf-8
'''
Created on 2015年9月10日

@author: laughlast
'''
import os
import unittest2


class BaseDemo(unittest2.TestCase):

    '''BaseDemo: all ok except test_step_2'''

    def test_step_1(self):
        '''base'''
        assert True

    def test_step_2(self):
        '''base'''
        self.fail('fail()')

    def test_step_3(self):
        '''base'''
        assert True

    def test_step_4(self):
        '''base'''
        assert True

    def test_step_5(self):
        '''base'''
        assert True

    def test_step_6(self):
        '''base'''
        assert True

    def test_step_7(self):
        '''base'''
        assert True

    def test_step_8(self):
        '''base'''
        assert True

    def test_step_9(self):
        '''base'''
        assert True


class BizDemo1(BaseDemo):

    '''BizDemo1'''
    pass


class BizDemo2(BaseDemo):

    '''BizDemo2'''
    pass


class BizDemo3(BaseDemo):

    '''BizDemo3'''
    pass


class BizDemo4(BaseDemo):

    '''BizDemo4'''
    pass


class BizDemo5(BaseDemo):

    '''BizDemo5'''
    pass


class BizDemo6(BaseDemo):

    '''BizDemo6'''
    pass


class BizDemo7(BaseDemo):

    '''BizDemo7'''

    def test_step_2(self):
        '''BizDemo7 all ok'''
        assert True

if __name__ == "__main__":
    tloader = unittest2.defaultTestLoader
    tpath = os.path.split(os.path.realpath(__file__))[0]
    tsuite = tloader.discover(tpath, 'test_failfast*.py')
    trunner = unittest2.TextTestRunner(failfast=True)
    tresult = trunner.run(tsuite)
    print tresult
    assert tresult.testsRun == 2 * 7 + 9 \
        and len(tresult.failures) == 7

执行结果参考:

----------------------------------------------------------------------

Ran 23 tests in 0.000s


FAILED (failures=7)

<unittest2.runner.TextTestResult run=23 errors=0 failures=7>

相关文章
相关标签/搜索