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
,否則返回 False
。expectedFailure()返回成功為不通過
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的核心類,從開始到結束都會使用到,所以需要熟悉其用法,以供測試框架的擴展和開發。