HTMLTestRunner是Python标准库unittest单元测试框架的一个扩展,它生成易于使用的HTML测试报告。HTMLTestRunner是在BSD许可证下发布的。
下载地址如下:
http://tungwaiyip.info/software/HTMLTestRunner.html
这个扩展非常简单,只有一个HTMLTestRunner.py文件,选中后单击鼠标右键,在弹出的快捷菜单中选择目标另存为,将它保存到本地。安装方法也很简单,将其复制到Python安装目录下即可。
Windows:将下载的文件保存到...\Python35\Lib目录下。
在Python交互模式下引入HTMLTestRunner模块,如果系统没有报错,则说明添加成功。
import HTMLTestRunner
一、修改HTMLTestRunner
因为HTMLTestRunner.py是基于Python2开发的,为了使其支持Python3的环境,需要对其中的部分内容进行修改。下面通过编辑器打开HTMLTestRunner.py文件。
#第94行
import StringIO
修改为:
import io
#第539行
self.outputBuffer = StringIO.StringIO()
修改为:
self.outputBuffer = io.StringIO()
#第631行
print >>sys.stderr, '\nTime Elapsed: %s' % (self.stopTime-self.startTime)
修改为:
print(sys.stderr, '\nTime Elapsed: %s' % (self.stopTime-self.startTime))
#第642行
if not rmap.has_key(cls):
修改为:
if not cls in rmap:
#第766行
uo=o.decode('latin-1')
修改为:
uo=e
#第772行
ue=e.decode('latin-1')
修改为:
ue=e
二、生成HTML测试报告
下面继续以test_baidu.py文件为例生成HTMLTestRunner测试报告。
test_baidu.py
from selenium import webdriver
import unittest
from selenium.webdriver.support.wait import WebDriverWait
class SearchTestCase(unittest.TestCase):
def setUp(self):
self.driver=webdriver.Chrome()
self.driver.maximize_window()
self.driver.get("http://www.baidu.com")
self.driver.implicitly_wait(15)
def test_serchChina(self):
"""百度搜索中国的测试用例"""
self.driver.find_element_by_xpath(".//*[@id='kw']").send_keys("中国")
self.driver.find_element_by_xpath(".//*[@id='su']").click()
WebDriverWait(self.driver, 15).until(lambda x: x.find_element_by_xpath(".//*[@id='1']/h3/a"))
result = self.driver.find_element_by_xpath(".//*[@id='1']/h3/a").text
self.assertEqual(result, "中国_百度百科")
def tearDown(self):
self.driver.close()
self.driver.quit()
if __name__ == '__main__':
unittest.main()
代码分析
首先,将HTMLTestRunner模块用import导入进来。
其次,通过open()方法以二进制写模式打开当前目录下的result.html,如果没有,则自动创建该文件。
接着,调用HTMLTestRunner模块下的HTMLTestRunner类。stream指定测试报告文件,title用于定义测试报告的标题,description用于定义测试报告的副标题。
最后,通过HTMLTestRunner的run()方法来运行测试套件中所组装的测试用例。最后通过close()关闭测试报告文件。
用例运行完成,打开当前目录下的“result.html”文件查看生成的测试报告。
运行中遇到无法生成报告,按如下方法进行可生成报告。
三、更易读的测试报告
现在生产的测试报告还不易读,因为它只罗列了一堆测试类和测试方法,我们需要用心地为测试类和测试方法命名才能提高测试报告的可读性。如果随意命名为"test_case1"、“test_case2"等,那么这份报告就失去了可读性,也许时间久了连脚本开发者都不清楚"test_case1"是测试什么功能了。
在编写功能测试用例时,每条测试用例都有标题,那么我们能不能也为自动化测试用例加上标题呢?在此之前我们先来学习另外一个知识点:Pathon注释。Python的注释有两种,一种叫comment,另一种叫doc string,前者为普通的注释,后者用于函数、类和方法的描述。
python shell
def add(a,b): "add()函数需要两个入参,并返回两个参数相加的值。" return a+b print(add(2,4)) print(help(add))
输出:
在类或方法的下方,通过三引号""" """或''' '''来添加doc string类型的注释,这类注释在平时调用的时候不显示,可以通过help()方法来查看类或方法的这种注释。
回到问题的原点,HTMLTestRunner可以读取doc string 类型的注释。所以,我们只需给测试类或方法添加这种类型的注释即可。
baidu.py
from selenium import webdriver import unittest from HTMLTestRunner import HTMLTestRunner #测试记录1 class Baidu(unittest.TestCase): '''百度搜索测试''' def setUp(self): self.driver=webdriver.Chrome() self.driver.implicitly_wait(10) self.base_url="http://www.baidu.com" #测试记录2 def test_baidu_search(self): '''搜索关键字:HTMLTestRunner''' driver=self.driver driver.get(self.base_url) driver.find_element_by_id("kw").send_keys("HTMLTestRunner") driver.find_element_by_id("su").click() def tearDown(self): self.driver.quit() if __name__=="__main__": testunit = unittest.TestSuite() testunit.addTest(Baidu("test_baidu_search")) # 定义报告存放路径 fp = open('result.html','wb') # 定义测试报告 runner = HTMLTestRunner(stream=fp,title='百度搜索测试报告',description='用例执行情况:') runner.run(testunit) # 运行测试用例 fp.close() # 关闭报告文件
再次运行测试用例,查看测试报告
四、测试报告文件名
在每次运行测试之前,都要手动修改报告的名称,如果忘记修改,就会把之前的报告覆盖,这样做显然很麻烦,那么有没有办法使每次生成的报告名称都不重叠,又能更清晰地知道报告的生成时间。
Python的time模块中提供了丰富的关于时间操作的方法,可以利用这些方法来完成这个需求。
输入
输出:
time.time():获取当前时间戳 time.ctime():当前时间的字符串形式 time.localtime():当前时间的struct_time形式 time.strftime("%Y_%m_%d %H:%M:%S"):用来获得当前时间,可以将时间格式化为字符串。
Python中时间日期格式化符号(区分大小写)
指令 | 含义 |
%a | 星期几的简写 |
%A | 星期几的全称 |
%w | 十进制表示的星期几(值从0到6,星期天为0) |
%d | 十进制表示的每月的第几天 |
%b | 月份的简写 |
%B | 月份的全称 |
%m | 十进制表示的月份 |
%y | 不带世纪的十进制年份(值从0到99) |
%Y | 带世纪部分的十制年份 |
%H | 24小时制的小时 |
%I | 12小时制的小时 |
%p | 本地的AM或PM的等价显示 |
%M | 十时制表示的分钟数 |
%S | 十进制的秒数 |
%f | 十进制的微妙,零填充左边 |
%Z | 当前时区的名称 |
%j | 十进制表示的每年的第几天 |
%U | 一年中的星期数(00-53),星期天为星期的开始 |
%W | 一年中的星期数(00-53),星期一为星期的开始 |
%x | 本地相应的日期表示 |
%X | 本地相应的日期表示 |
%% | %号本身 |
继续打开测试用例,做如下修改。
from selenium import webdriver import unittest from HTMLTestRunner import HTMLTestRunner import time #测试记录1 class Baidu(unittest.TestCase): '''百度搜索测试''' def setUp(self): self.driver=webdriver.Chrome() self.driver.implicitly_wait(10) self.base_url="http://www.baidu.com" #测试记录2 def test_baidu_search(self): '''搜索关键字:HTMLTestRunner''' driver=self.driver driver.get(self.base_url) driver.find_element_by_id("kw").send_keys("HTMLTestRunner") driver.find_element_by_id("su").click() def tearDown(self): self.driver.quit() #测试方法3 if __name__=="__main__": testunit = unittest.TestSuite() testunit.addTest(Baidu("test_baidu_search")) # 按照一定格式获取当前时间 now=time.strftime("%Y-%m-%d %H_%M_%S") #定义报告存放路径 filename='./'+now+'result.html' fp = open(filename,'wb') # 定义测试报告 runner = HTMLTestRunner(stream=fp,title='百度搜索测试报告',description='用例执行情况:') runner.run(testunit) # 运行测试用例 fp.close() # 关闭报告文件
通过strftime()方法以指定的格式获取当前时间,将当前时间的字符串赋值给now变量。将now通过加号(+)拼接到生成的测试报告的文件名中。再次运行测试用例,生成的测试报告文件名。
五、项目集成测试报告
目前HTMLTestRunner只是针对单个测试文件生成测试报告,我们的最终目的是希望将它集成到runtest.py文件汇总,使其作用于整个测试项目。下面打开runtest.py文件进行修改。
import unittest,time from HTMLTestRunner import HTMLTestRunner #指定测试用例为当前文件夹下的test_case目录 test_dir='./test_case' discover=unittest.defaultTestLoader.discover(test_dir,pattern='test_*.py') if __name__=='__main__': now = time.strftime("%Y-%m-%d %H_%M_%S") # 定义报告存放路径 filename = './' + now + 'result.html' fp = open(filename, 'wb') # 定义测试报告 runner = HTMLTestRunner(stream=fp, title='百度搜索测试报告', description='用例执行情况:') runner.run(discover) # 运行测试用例 fp.close() # 关闭报告文件
报告为: