python中test,htmltestrunner生成测试报告
计算机编程语言使用TestLoader、TestSuite、HTMLTestRunner组织测试用例实例_weltest的技术博客_博客
http://tungwaiyip.info/software/HTMLTestRunner.html
上述的生成超文本标记语言格式的测试报告的库文件下载链接,如果下载不成,我会在文章底部附上该文件源码。
该篇文章是讲述一个文件包含两个测试用例,如何组织运行。整体的架构如下:
关于计算器前的文章有相应的源码。可以找到,下面附出withTestLoader.py的源码:
#编码=utf8
单元测试提供一个测试加载器类用于自动创建一个测试集并把单个测试放入到测试集中。
测试加载器自动运行测试用例以试验开头的方法的测试方法。
在多个测试用例在决定运行哪个测试用例的策略是通过内建函数对测试函数名排序决定的。
通常习惯将测试集组合在一起,以便系统一次运行所有的测试用例。
测试集实例添加到一个测试集中就像把一个测试案例实例添加到一个测试集中。
-
套件1=模块1。测试套件()
套件2=模块2。测试套件()
alltests=unittest .测试套件([套件1,套件2])
-
可以将测试用例和测试套件的定义放在与要测试的代码相同的模块中,但将测试代码放在单独的模块中有几个好处:
1、测试模块可以从命令行独立运行。
2、测试代码可以更容易地与运输代码分开。
3、有更少的诱惑改变测试代码,以适应代码测试没有一个很好的理由。
4、测试代码的修改频率要比它测试的代码少得多。
5、测试代码可以更容易重构。
6、用C编写的模块的测试必须在单独的模块中,所以为什么不一致?
7、如果测试策略更改,则不需要更改源代码。
从__未来_ _进口部门
来自解放号.乱码导入乱码
从单元测试导入测试用例、测试加载器、测试套件
从来源.计算器导入计算器类
类TestMul(测试用例):
定义设置(自身):
及格
def test_defaultMul(self):
cal=calculatorClass()
self.assertEqual(cal.mul(),200,结果应该等于200 )
def test _ connectivimul(self):
cal=calculatorClass(-10,-25)
self.assertEqual(cal.mul(),250,结果应该等于250 )
def test_floatMul(self):
cal=calculatorClass(0.25,0.4)
self.assertEqual(cal.mul(),0.1,结果应该等于0.1 )
定义拆卸(自身):
及格
类TestDiv(TestCase):
定义设置(自身):
及格
def test_defaultDiv(self):
cal=calculatorClass()
self.assertEqual(cal.mul(),0.5,”结果应该等于0.5 )
def test _ negative div(自身):
cal=calculatorClass(-10,-25)
self.assertEqual(cal.mul(),0.4,结果应该等于250 )
def test_floatDiv(self):
cal=calculatorClass(0.24,0.4)
self.assertEqual(cal.mul(),0.6,”结果应该等于0.1 )
定义拆卸(自身):
及格
def allTest():
创建测试集
suite1=TestLoader().loadTestsFromTestCase(TestMul)
suite2=TestLoader().loadTestsFromTestCase(TestDiv)
alltests=TestSuite([suite1,suite2])
返回所有测试
if __name__==__main__ :
创建保存测试结果的文件
html=文件(.\\report.html , wb )
调用乱码类生成超文本标记语言格式测试运行报告
runner=html测试运行程序(stream=html,title=测试报告,描述=运行测试用例的状态)
runner.run(allTest())
html.close()
测试运行结果报告如下:
附录:
HTMLTestRunner.py
用于计算机编程语言单元测试框架的测试跑步者.它
生成一个超文本标记语言报告来快速显示结果。
使用它的最简单的方法是调用它的主要的方法。例如
导入单元测试
导入乱码
.定义您的测试.
if __name__==__main__ :
HTMLTestRunner.main()
对于更多自定义选项,实例化一个乱码对象。
乱码是单元测试的TextTestRunner的对等物。例如
#输出到文件
fp=file(my_report.html , wb )
runner=HTMLTestRunner .HTMLTestRunner(
stream=fp,
标题=我的单元测试,
描述=这演示了乱码的报告输出。
)
#使用外部样式表。
#查看模板_混合类以获得更多可定制的选项
奔跑者.样式表_ TMPL= link rel=样式表 href= my _样式表。CSS type= text/CSS
#运行测试
runner.run(我的测试套件)
-
版权所有(c) 2004-2007年,伟业通
保留所有权利。
以源代码和二进制形式重新分发和使用,有或没有
如果满足以下条件,则允许修改
符合:
*源代码的再分发必须保留上述版权声明,
此条件列表和以下免责声明。
*二进制形式的再分发必须复制上述版权
注意,此条件列表和
分发时提供的文档和/或其他材料。
*伟业通的名称或其出资人的姓名不得
用于认可或推广由此软件衍生的产品,而不
特定的事先书面许可。
本软件由版权所有者和贡献者提供
以及任何明示或暗示的保证,包括但不限于
的适销性和适用性的默示保证
拒绝特殊用途。在任何情况下,版权所有者不得
或贡献者对任何直接、间接、附带、特殊,
惩戒性或后果性损害(包括但不限于,
采购替代货物或服务;用途、数据或的损失
利润;或业务中断),无论是何种原因造成的
责任,无论是合同责任、严格责任还是侵权责任(包括
疏忽或其他原因)引起的任何后果
软件,即使已被告知可能出现此类损坏。
#网址:http://tungwaiyip . info/software/html test runner . html
__作者__=伟业通
__版本__=0.8.2
改变历史
版本0.8.2
*显示内联输出,而不是弹出窗口(维奥雷尔卢普)。
0.8.1版本
*经过验证的XHTML (Wolfgang Borgert).
*增加了测试类和测试用例的描述。
0.8.0版本
*为定制定义模板_混合类。
*解决了IE 6的一个错误,即它不会将脚本块视为CDATA .
0.7.1版本
*回移植到Python 2.3(弗兰克霍洛维茨).
*修复详细日志(珀迪)中丢失的滚动条。
# TODO:颜色标准错误
# TODO:使用班级属性中的一个或多个类来简化javascript?
导入日期时间
进口斯特林乔
导入系统
导入时间
导入单元测试
从xml.sax导入萨克斯蒂尔斯
# -
#下面的重定向器用于在测试过程中捕获输出。输出
#发送到sys.stdout和sys.stderr是自动捕获的。然而
#在某些情况下,sys.stdout已经在乱码之前缓存
#已调用(例如调用logging.basicConfig).为了捕捉那些
#输出,使用缓存流的重定向器。
#
#例如
#日志记录。基本配置(stream=htmltestrunner。标准输出重定向器)
#
类输出目录(对象):
重定向标准输出或标准错误包装
def __init__(self,fp):
self.fp=fp
定义写入(自身,秒):
self.fp.write
定义写入行(自身,行):
self.fp.writelines(行)
定义冲洗(自身):
self.fp.flush()
stdout _ redirector=输出控制器(sys。stdout)
stderr _ redirector=输出控制器(sys。stderr)
# -
#模板
类模板_mixin(对象):
为报告定制和生成定义一个超文本标记语言模板。
超文本标记语言报告的整体结构
超文本标记语言
-
html
头部
样式表
-
-
self.stdout0=sys.stdout
self.stderr0=sys.stderr
sys.stdout=stdout _ redirector
sys.stderr=stderr _重定向器
定义完成_输出(自身):
断开输出重定向和返回缓冲区。
多次调用是安全的。
if self.stdout0:
sys.stdout=self.stdout0
sys。标准错误=自我。标准错误0
self.stdout0=无
self.stderr0=None
返回self.outputBuffer.getvalue()
定义停止测试(自我,测试):
#通常会调用addSuccess、addError或添加失败中的一个。
#但是单元测试中有一些路径可以绕过这一点。
#我们必须在停止测试()中断开stdout,它保证会被调用。
self.complete_output()
def addSuccess(自我,测试):
self.success_count=1
TestResult.addSuccess(self,test)
output=self.complete_output()
self.result.append((0,test,output,))
if self.verbosity 1:
sys.stderr.write(ok )
sys.stderr.write(str(test))
sys.stderr.write(\n )
否则:
sys.stderr.write( . )
def addError(self,test,err):
self.error_count=1
TestResult.addError(self,test,err)
_,_exc_str=self.errors[-1]
output=self.complete_output()
self.result.append((2,test,output,_exc_str))
if self.verbosity 1:
sys.stderr.write(E )
sys.stderr.write(str(test))
sys.stderr.write(\n )
否则:
sys.stderr.write(E )
def addFailure(self,test,err):
self.failure_count=1
TestResult.addFailure(self,test,err)
_,_exc_str=self.failures[-1]
output=self.complete_output()
self.result.append((1,test,output,_exc_str))
if self.verbosity 1:
sys.stderr.write(F )
sys.stderr.write(str(test))
sys.stderr.write(\n )
否则:
sys.stderr.write(F )
类HTMLTestRunner(Template_mixin):
def __init__(self,stream=sys.stdout,verbosity=1,title=None,description=None):
自我流=流
self.verbosity=冗长
如果标题为无:
self.title=自我.默认_标题
否则:
self.title=标题
如果描述为无:
自我描述=自我。默认_描述
否则:
自我描述=描述
自我。开始时间=日期时间。日期时间。现在()
定义运行(自检、测试):
运行给定的测试用例或测试套件。
结果=_测试结果(自身。冗长)
测试(结果)
自我。停止时间=日期时间。日期时间。现在()
自我生成报告(测试,结果)
已用时间:% s %(自身。停止时间自我。开始时间)
回送结果
def sortResult(self,result_list):
#单元测试似乎没有按任何特定的顺序运行。
#这里至少我们想把他们按类分组。
rmap={}
classes=[]
对于结果列表中的北、东、西、东:
cls=t.__class__
如果不是rmap.has_key(cls):
rmap[cls]=[]
班级。追加(cls)
rmap[cls].追加((n,t,o,e))
r=[(cls,rmap[cls]) for cls in classes]
返回r
def getReportAttributes(self,result):
以(名称,值)列表的形式返回报表属性。
覆盖它以添加自定义属性。
开始时间=str(self。开始时间)[:19]
持续时间=str(self。停止时间自我。开始时间)
状态=[]
如果结果。成功计数:状态。追加(传递% s %结果。成功_计数)
如果结果。失败计数:状态。追加(失败%s % result.failure_count)
如果结果。错误计数:状态。追加(错误% s %结果。错误计数)
如果状态:
状态=""。加入(状态)
否则:
状态=无
返回[
(开始时间,开始时间),
(持续时间,持续时间),
(状态,状态),
]
定义生成报告(自我、测试、结果):
报告_属性=自身。getreportattributes(结果)
生成器= HTMLTestRunner % s“% _ _ version _ _
样式表=自身. generate_stylesheet()
航向=自身。_生成_标题(报告_属性)
报告=自我。_生成_报告(结果)
结局=自我. generate_ending()
输出=自我. HTML_TMPL %字典(
title=sax utils。逃避(自我。标题),
发电机=发电机,
样式表=样式表,
航向=航向,
报告=报告,
结尾=结束,
)
自我。溪流。写(输出。编码( utf8 ))
定义_生成_样式表(自己):
回归自我。样式表_TMPL
定义_生成_标题(自身,报告属性):
a_lines=[]
对于名称,报告_属性中的值:
线=自我。标题_属性_TMPL %字典(
name=saxutils.escape(name),
value=saxutils.escape(value),
)
a_lines.append(line)
航向=自身。标题_TMPL %字典(
title=sax utils。逃避(自我。标题),
参数=""。加入(a_lines),
description=saxutils.escape(自我描述),
)
返回航向
定义_生成_报告(自身,结果):
行数=[]
排序结果=自身。排序结果(结果。结果)
对于cid,枚举(排序结果)中的(cls,cls_results):
#课程小计
np=nf=ne=0
对于cls _结果中的n、t、o、e:
如果n==0: np=1
elif n==1: nf=1
否则:ne=1
#格式化类别描述
如果cls .__模块__==__main__ :
name=cls .__姓名_ _
否则:
name=%s.%s % (cls .__模块_ _,cls .__name__)
doc=cls .__doc__和cls .__doc__ .拆分( \n)[0]或
desc=文档和% s:% s“%(名称,文档)或名称
行=自身。报告_类_TMPL %字典(
style=ne 0和错误类别或nf 0和失败类别或通行证类别,
desc=desc,
count=np nf ne,
Pass=np,
失败=nf,
误差=ne,
cid = c%s % (cid+1),
)
rows.append(row)
for tid, (n,t,o,e) in enumerate(cls_results):
self._generate_report_test(rows, cid, tid, n, t, o, e)
report = self.REPORT_TMPL % dict(
test_list = .join(rows),
count = str(result.success_count+result.failure_count+result.error_count),
Pass = str(result.success_count),
fail = str(result.failure_count),
error = str(result.error_count),
)
return report
def _generate_report_test(self, rows, cid, tid, n, t, o, e):
# e.g. pt1.1, ft1.1, etc
has_output = bool(o or e)
tid = (n == 0 and p or f) + t%s.%s % (cid+1,tid+1)
name = t.id().split(.)[-1]
doc = t.shortDescription() or ""
desc = doc and (%s: %s % (name, doc)) or name
tmpl = has_output and self.REPORT_TEST_WITH_OUTPUT_TMPL or self.REPORT_TEST_NO_OUTPUT_TMPL
# o and e should be byte string because they are collected from stdout and stderr?
if isinstance(o,str):
# TODO: some problem with string_escape: it escape \n and mess up formating
# uo = unicode(o.encode(string_escape))
uo = o.decode(latin-1)
else:
uo = o
if isinstance(e,str):
# TODO: some problem with string_escape: it escape \n and mess up formating
# ue = unicode(e.encode(string_escape))
ue = e.decode(latin-1)
else:
ue = e
script = self.REPORT_TEST_OUTPUT_TMPL % dict(
id = tid,
output = saxutils.escape(uo+ue),
)
row = tmpl % dict(
tid = tid,
Class = (n == 0 and hiddenRow or none),
style = n == 2 and errorCase or (n == 1 and failCase or none),
desc = desc,
script = script,
status = self.STATUS[n],
)
rows.append(row)
if not has_output:
return
def _generate_ending(self):
return self.ENDING_TMPL
##############################################################################
# Facilities for running tests from the command line
##############################################################################
# Note: Reuse unittest.TestProgram to launch test. In the future we may
# build our own launcher to support more specific command line
# parameters like test title, CSS, etc.
class TestProgram(unittest.TestProgram):
"""
A variation of the unittest.TestProgram. Please refer to the base
class for command line parameters.
"""
def runTests(self):
# Pick HTMLTestRunner as the default test runner.
# base classs testRunner parameter is not useful because it means
# we have to instantiate HTMLTestRunner before we know self.verbosity.
if self.testRunner is None:
self.testRunner = HTMLTestRunner(verbosity=self.verbosity)
unittest.TestProgram.runTests(self)
main = TestProgram
##############################################################################
# Executing this module from the command line
##############################################################################
if __name__ == "__main__":
main(module=None)
©
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。