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的核心类,从开始到结束都会使用到,所以需要熟悉其用法,以供测试框架的扩展和开发。