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>

相關文章
相關標籤/搜索