unittest單元測試框架教程8-unittest.TestResult類詳解


unittest.TestResult用於編譯有關哪些測試成功和失敗的信息。一個TestResult對象存儲一組測試的結果。TestRunner.run()方法返回一個TestResult實例以便於生成測試報告。

TestResult 實例具有以下屬性

依然測試此類

import unittest

def jiafa(a,b):
if type(a) is str or type(b) is str:
return str(a) + str(b)
return a+b

def jianfa(a,b):
if type(a) is str or type(b) is str:
return 0
return a-b

def chengfa(a,b):
if type(a) is str or type(b) is str:
return 0
return a*b

def chufa(a,b):
if type(a) is str or type(b) is str:
return 0
return a/b

class TestMath(unittest.TestCase):
def setUp(self):
pass

def tearDown(self):
pass

def test_jiafa(self):
'''測試加法程序'''
print("開始測試test_jiafa")
self.assertEqual(jiafa('a',1),'a1')

def test_jianfa(self):
'''測試減法程序'''
print("開始測試test_jianfa")
self.assertEqual(jianfa('a',1),0)

def test_chengfa(self):
'''測試乘法程序'''
print("開始測試test_chengfa")
self.assertEqual(chengfa('a',1),'a')

def test_chufa(self):
'''測試乘法程序'''
print("開始測試test_chufa")
self.assertEqual(chufa(0,0),0)

if __name__ == '__main__':
unittest.main()

其中乘法程序是有問題,預期會返回錯誤

 

errors

包含2個元組的TestCase實例和包含格式化回溯的字符串的列表每個元組代表一個引發意外異常的測試。

runner = unittest.TextTestRunner(verbosity=0)
suite = unittest.TestSuite()
suite.addTest(TestAdd('test_chufa'))
result = runner.run(suite)
print(result.errors)

開始測試test_chufa
[(<testmath.TestMath testMethod=test_chufa>, 'Traceback (most recent call last):\n File "D:\\PycharmProjects\\unitest\\testmath.py", line 99, in test_chufa\n self.assertEqual(chufa(0,0),0)\n File "D:\\PycharmProjects\\unitest\\testmath.py", line 72, in chufa\n return a/b\nZeroDivisionError: division by zero\n')]
======================================================================
ERROR: test_chufa (testmath.TestMath)
測試乘法程序
----------------------------------------------------------------------
Traceback (most recent call last):
File "D:\PycharmProjects\unitest\testmath.py", line 99, in test_chufa
self.assertEqual(chufa(0,0),0)
File "D:\PycharmProjects\unitest\testmath.py", line 72, in chufa
return a/b
ZeroDivisionError: division by zero

----------------------------------------------------------------------
Ran 1 test in 0.001s

FAILED (errors=1)

 

failures

包含2個元組的TestCase實例和包含格式化回溯的字符串的列表每個元組代表一個測試,其中使用這些TestCase.assert*()方法明確指示了失敗

runner = unittest.TextTestRunner(verbosity=0)
suite = unittest.TestSuite()
suite.addTest(TestMath('test_chengfa'))
result = runner.run(suite)
print(result.failures)

開始測試test_chengfa
[(<testmath.TestMath testMethod=test_chengfa>, 'Traceback (most recent call last):\n File "D:\\PycharmProjects\\unitest\\testmath.py", line 94, in test_chengfa\n self.assertEqual(chengfa(\'a\',1),\'a\')\nAssertionError: 0 != \'a\'\n')]
======================================================================
FAIL: test_chengfa (testmath.TestMath)
測試乘法程序
----------------------------------------------------------------------
Traceback (most recent call last):
File "D:\PycharmProjects\unitest\testmath.py", line 94, in test_chengfa
self.assertEqual(chengfa('a',1),'a')
AssertionError: 0 != 'a'

----------------------------------------------------------------------
Ran 1 test in 0.001s

FAILED (failures=1)

 

skipped

包含2元組的TestCase實例和字符串的列表,其中包含跳過測試的原因。

@unittest.skip的方法

 

expectedFailures

包含2個元組的TestCase實例和包含格式化回溯的字符串的列表每個元組代表測試用例的預期失敗。

@unittest.expectedFailure的方法

 

unexpectedSuccesses

包含TestCase標記為預期失敗但成功的實例的列表。

@unittest.expectedFailure的但是運行成功的方法

 

shouldStop

設置為何True時suite.run(result)不進行測試以及不記錄運行次數。

result = unittest.TestResult()
unittest.registerResult(result)
loader = unittest.TestLoader()
testmethod = loader.getTestCaseNames(TestMath)
for t in testmethod:
result.shouldStop = False
if t == 'test_chufa':
result.shouldStop = True
suite = unittest.TestSuite()
suite.addTest(TestMath(t))
result = suite.run(result)
print(result)

開始測試test_chengfa
開始測試test_jiafa
開始測試test_jianfa
<unittest.result.TestResult run=3 errors=0 failures=1>

test_chufa沒有執行

 

testsRun

到目前為止,測試總數。

 

result = unittest.TestResult()
unittest.registerResult(result)
loader = unittest.TestLoader()
testmethod = loader.getTestCaseNames(TestMath)
for t in testmethod:
suite = unittest.TestSuite()
suite.addTest(TestMath(t))
result = suite.run(result)
print('測試總數為'+str(result.testsRun))

開始測試test_chengfa
測試總數為1
開始測試test_chufa
測試總數為2
開始測試test_jiafa
測試總數為3
開始測試test_jianfa
測試總數為4

 

buffer

TextTestRunner對象的buffer參數

 

failfast

TextTestRunner對象的failfast參數

 

tb_locals

TextTestRunner對象的tb_locals參數

 

wasSuccessful()

如果所有的測試運行通過返回True,否則返回 FalseexpectedFailure()返回成功為不通過

result = unittest.TestResult()
unittest.registerResult(result)
loader = unittest.TestLoader()
suite = loader.loadTestsFromTestCase(TestMath)
result = suite.run(result)
print('測試是否全部通過'+str(result.wasSuccessful()))

開始測試test_chengfa
開始測試test_chufa
開始測試test_jiafa
開始測試test_jianfa
測試是否全部通過False

TestResult類的以下方法用於維護內部數據結構,並且可以在子類中擴展以支持其他報告要求。這對於在運行測試時支持交互式報告的構建工具特別有用。

下面以在某文件寫入測試過程為例

class MyTestResult(unittest.TestResult):
    def __init__(self, *args, **kwds):
        super(MyTestResult,self).__init__(self)
        try:
            self.resultfile = open('testtext.txt','w+',encoding='utf-8')
        except Exception as e:
            pass

    def startTestRun(self):
        '''在執行任何測試之前調用一次。'''
        super(MyTestResult, self).startTestRun()
        if self.resultfile.writable():
            self.resultfile.writelines('單元測試開始!')
            self.resultfile.writelines('\n')

    def stopTestRun(self):
        '''執行完所有測試后調用一次。'''
        super(MyTestResult, self).stopTestRun()
        if self.resultfile.writable():
            self.resultfile.writelines('單元測試結束!')
            self.resultfile.writelines('\n')

    def startTest(self,test):
        '''在測試用例測試即將運行時調用。'''
        super(MyTestResult,self).startTest(test)
        if self.resultfile.writable():
            self.resultfile.writelines('開始運行' + test.shortDescription())
            self.resultfile.writelines('\n')

    def stopTest(self, test):
        '''不管結果如何,在執行完測試用例測試之后調用。'''
        super(MyTestResult, self).stopTest(test)
        if self.resultfile.writable():
            self.resultfile.writelines('結束運行' + test.shortDescription())
            self.resultfile.writelines('\n')
loader
= unittest.TestLoader() suite = loader.loadTestsFromTestCase(TestAdd) runner = unittest.TextTestRunner(resultclass=MyTestResult) result = runner.run(suite) print(result)

運行后查看testtext.txt文件

單元測試開始!
開始運行測試加法程序
結束運行測試加法程序
開始運行測試乘法程序
結束運行測試乘法程序
開始運行測試除法程序
結束運行測試除法程序
開始運行測試減法程序
結束運行測試減法程序
單元測試結束!

 還可以加入單個用例的運行結果

    def addError(self, test, err):
        '''在測試用例測試引發意外異常時調用。'''
        super(MyTestResult, self).addError(test, err)
        self.resultfile.writelines(test.shortDescription() + test.id() + '發現異常' + str(err))
        self.resultfile.writelines('\n')

    def addFailure(self, test, err):
        '''在測試用例測試發出失敗信號時調用。'''
        super(MyTestResult, self).addFailure(test, err)
        self.resultfile.writelines(test.shortDescription() + test.id() + '發現錯誤' + str(err))
        self.resultfile.writelines('\n')

    def addSuccess(self,test):
        '''在測試用例測試成功時調用。'''
        super(MyTestResult, self).addSuccess(test)
        self.resultfile.writelines(test.shortDescription()+test.id()+'運行通過')
        self.resultfile.writelines('\n')
單元測試開始!
開始運行測試加法程序
測試加法程序testmath.TestAdd.test_add1運行通過
結束運行測試加法程序
開始運行測試乘法程序
測試乘法程序testmath.TestAdd.test_chengfa發現錯誤(<class 'AssertionError'>, AssertionError('3 != 2 : 乘法程序錯誤'), <traceback object at 0x03C91F58>)
結束運行測試乘法程序
開始運行測試除法程序
測試除法程序testmath.TestAdd.test_chufa發現異常(<class 'ZeroDivisionError'>, ZeroDivisionError('division by zero'), <traceback object at 0x03CB5F58>)
結束運行測試除法程序
開始運行測試減法程序
測試減法程序testmath.TestAdd.test_minus運行通過
結束運行測試減法程序
單元測試結束!

 

addSubTest(test, subtest, outcome)

子測試完成時調用。 test是與測試方法相對應的測試用例。 subtest是子測試生成的TestCase對象的自定義實例。

如果subtest結果為None,則subtest通過。否則,它會失敗,並有一個異常,即結果是由(type, value, traceback)返回的sys.exc_info()元組。

加入一個測試用例,驗證加法減法乘法用例相加的值是否為4

def test_all(self):
'''測試組合計算'''
testlist = [{'testmethod': 'test_jiafa'}, {'testmethod': 'test_jianfa'}, {'testmethod': 'test_chengfa'},
{'testmethod': 'test_chufa'}]
num = 0
for t in testlist:
with self.subTest(t):
testmethod = t['testmethod']
testfunc = getattr(self, testmethod)
testfunc()

testrunner.py中加入addSubTest方法

    def addSubTest(self, test, subtest, err):
        super(MyTestResult, self).addSubTest(test, subtest, err)
        if err == None:
            self.resultfile.writelines(subtest.id() + '運行通過')
            self.resultfile.writelines('\n')
        elif err[0] == AssertionError:
            self.resultfile.writelines(subtest.id() + '發現步驟錯誤' + str(err))
            self.resultfile.writelines('\n')
        else:
            self.resultfile.writelines(subtest.id() + '發現步驟異常' + str(err))
            self.resultfile.writelines('\n')

suite = unittest.TestSuite()
suite.addTest(TestAdd('test_all'))
runner = unittest.TextTestRunner(resultclass=MyTestResult)
result = runner.run(suite)
print(result)

運行后查看testtext.txt,可以看到具體哪一個測試步驟的異常和錯誤

單元測試開始!
開始運行測試組合計算
testmath.TestMath.test_all [{'testmethod': 'test_jiafa'}]運行通過
testmath.TestMath.test_all [{'testmethod': 'test_jianfa'}]運行通過
testmath.TestMath.test_all [{'testmethod': 'test_chengfa'}]發現步驟錯誤(<class 'AssertionError'>, AssertionError("0 != 'a'"), <traceback object at 0x02FADFD0>)
testmath.TestMath.test_all [{'testmethod': 'test_chufa'}]發現步驟異常(<class 'ZeroDivisionError'>, ZeroDivisionError('division by zero'), <traceback object at 0x02FBC148>)
結束運行測試組合計算
單元測試結束!

 

unittest.TestResult類是unittest的核心類,從開始到結束都會使用到,所以需要熟悉其用法,以供測試框架的擴展和開發。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM