pyunit扩展:自定义测试结果类型

pyunit中的测试结果包括Pass、Fail、Error三种类型。但是很多时候,仅仅三种类型不足以区分。

比如当某些用例所依赖的外部环境不具备时,或者因为某些已知缺陷导致用例必然失败,等等。

如果执行这些用例,会浪费时间;如果不执行,又难以从测试报告中清晰的看到原因。扩展测试结果的类型能帮助我们解决这个问题。


#add a new method to set user defined result, such as block, investigation...
class UserDefinedResultTestCase(TestCase):
	#@see TestCase.fail
	def setresult(self, resulttype, msg):
		raise self.failureException(UserDefinedResult.sealresult(resulttype, msg))

class UserDefinedResult(TextTestResult):
	#seal and unseal user defined result by FAILURE
	@staticmethod
	def getMsgSepetor():
		return ':::'
	@staticmethod
	def sealresult(resulttype, msg):
		return resulttype + UserDefinedResult.getMsgSepetor() + msg
	@staticmethod
	def unsealresult(err):
		if isinstance(err, tuple):
			if isinstance(err[1], AssertionError):
				errmsg = err[1].message
				errinfo = errmsg.split(UserDefinedResult.getMsgSepetor())
				if len(errinfo) == 2:
					return errinfo
		return None
	@staticmethod
	def unsealresultstr(errmsg):
		errmsgbegin = errmsg.find('AssertionError:')
		if errmsgbegin > 1:
			errinfo = errmsg[errmsgbegin + 16:].strip().split(UserDefinedResult.getMsgSepetor())
			if len(errinfo) == 2:
				return errinfo
		return None
		
	#console output when fail, including user defined fail
	#@see TextTestResult.addFailure
	def addFailure(self, test, err):
		#just use TestResult's addFailure, not TextTestResult's
		super(TextTestResult, self).addFailure(test, err)
		
		fulltype = 'FAIL'
		shorttype = 'F'
		errinfo = UserDefinedResult.unsealresult(err)
		if not errinfo == None:
			fulltype = errinfo[0]
			shorttype = errinfo[0][0:1]
		
		if self.showAll:
			self.stream.writeln(fulltype)
		elif self.dots:
			self.stream.write(shorttype)
			self.stream.flush()
	
	#console output of detail info
	#@see TextTestResult.printErrors
	def printErrors(self):
		if self.dots or self.showAll:
			self.stream.writeln()
		self.printErrorList('ERROR', self.errors)
		
		self.failureDict = {}
		for aTest, aFailure in self.failures:
			failureinfo = UserDefinedResult.unsealresultstr(aFailure)
			if not failureinfo == None:
				if failureinfo[0] in self.failureDict.keys():
					self.failureDict[failureinfo[0]].append((aTest, aFailure))
				else:
					self.failureDict[failureinfo[0]] = [(aTest, aFailure)]
			else:
				if 'FAIL' in self.failureDict.keys():
					self.failureDict['FAIL'].append((aTest, aFailure))
				else:
					self.failureDict['FAIL'] = [(aTest, aFailure)]
		
		for errtype in self.failureDict.keys():
			self.printErrorList(errtype, self.failureDict[errtype])
	
	#console output of summary info
	#@see TextTestRunner.run
	def printFailureSummary(self):
		if not self.wasSuccessful():
			infos = []
			for errtype in self.failureDict.keys():
				infos.append('%s=%d' % (errtype, len(self.failureDict[errtype])))
			self.stream.writeln(" (%s)" % (", ".join(infos),))

#user defined TestProgram, set TestResult Class, print failure summary
#@see TestProgram.__init__
class UserDefinedTestProgram(TestProgram):
	def __init__(self, module='__main__', defaultTest=None, argv=None,
                    testLoader=loader.defaultTestLoader,
                    exit=True, verbosity=1, failfast=None, catchbreak=None,
                    buffer=None):
		mytestRunner = TextTestRunner(resultclass=UserDefinedResult)
		super(UserDefinedTestProgram, self).__init__(module, defaultTest, argv,
					mytestRunner, testLoader,
					False, verbosity, failfast, catchbreak,
					buffer)
					
		self.result.printFailureSummary()
		if exit:
			sys.exit(not self.result.wasSuccessful())

			
###############################			
					
class testdemo4(UserDefinedResultTestCase):
	def testpass(self):
		pass
	def testFail(self):
		self.fail('fail')
		
	def testUserDefinedResult1(self):
		self.setresult('DTS', '20140802115316133')
	def testUserDefinedResult2(self):
		self.setresult('DTS', '--------')
	def testUserDefinedResult3(self):
		self.setresult('REQ', 'you have to change it')
	def testUserDefinedResult4(self):
		self.setresult('ENV', 'no device exists')
	def testUserDefinedResult5(self):
		self.setresult('BLOCK', 'do not run')
	def testUserDefinedResult6(self):
		self.setresult('BLOCK', 'feature on old version')

###################

if __name__ == '__main__':
	UserDefinedTestProgram()

简单起见,我并没有彻底改造TestResult和TestCase,而是在结果输出的地方做了一些扩展,虽然代码有点牵强,但是改动的工作量和影响是比较小的,而且也达到了预期的效果。


执行的结果

FDDREBB.
========================================
FAIL: testFail (__main__.testdemo4)
----------------------------------------
Traceback (most recent call last):
AssertionError: fail
========================================
DTS: testUserDefinedResult1 (__main__.te
----------------------------------------
Traceback (most recent call last):
AssertionError: DTS:::20140802115316133
========================================
DTS: testUserDefinedResult2 (__main__.te
----------------------------------------
Traceback (most recent call last):
AssertionError: DTS:::--------
========================================
REQ: testUserDefinedResult3 (__main__.te
----------------------------------------
Traceback (most recent call last):
AssertionError: REQ:::you have to change
========================================
BLOCK: testUserDefinedResult5 (__main__.
----------------------------------------
Traceback (most recent call last):
AssertionError: BLOCK:::do not run
========================================
BLOCK: testUserDefinedResult6 (__main__.
----------------------------------------
Traceback (most recent call last):
AssertionError: BLOCK:::feature on old v
========================================
ENV: testUserDefinedResult4 (__main__.te
----------------------------------------
Traceback (most recent call last):
AssertionError: ENV:::no device exists
----------------------------------------
Ran 8 tests in 0.002s


FAILED (failures=7)
 (FAIL=1, DTS=2, REQ=1, BLOCK=2, ENV=1)


由于之前的账号【ist】注册邮箱一直修改不成功,无奈重新注册一个账号,将之前的帖子搬过来,原帖删除。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值