解决自动化测试中捕获断言之后,测试报告展示为ok无法查看具体哪条用例执行失败的问题
问题来自之前博客中折腾的单元测试异常捕获问题:自动化测试断言捕获
当时折腾出的解决方案是自定义测试报告的模板,定义status
状态位,作为测试用例执行结果的状态标志,一旦发生断言异常捕获,将status
状态为置为fail
,最后体现在测试报告上。
自定义报告
自定义报告模块,参考nose生成的报告,又东拼西凑折腾出了这份最简单的测试报告,最终报告生成原理就是:首先html文件中创建表格,预留html的尾部,在后续执行自动化测试过程中,将生成的测试数据拼接到不完整的html文件中,最终生成完成的html文件作为测试报告。
ReportTemplate.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
| #!/usr/bin/env python3 # -*- coding: utf-8 -*- """ @author: kyle @time: 2018/2/8 11:21 """
def htmlTemplate(trData): """自定义测试报告样式"""
htmlStr = u''' <!DOCTYPE html> <html lang="en"> <head> <title>Unit Test Report</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <style> body{ width: 80%; /* 整个body区域占浏览器百分比 */ margin: 40px auto; /* 整个body区域相对浏览器窗口摆放位置(左右,上下)*/、 font-weight: bold; /* 整个body区域字体加粗 */ font-family: Calibri, "Trebuchet MS", sans-serif; /* 表格中文字的字体类型 */ font-size: 18px; /* 字体大小 */ color: #000; } table{ border-spacing: 0; /* 表格边框宽度 */ width: 100%; /* 整个表格相对父元素的宽度 */ } .tableStyle{ border-style: outset; /* 整个表格外边框样式 */ border-width: 2px; /* 整个表格外边框宽度 */ border-color: blue; /* 整个表格外边框颜色 */ } .tableStyle tr:hover{ background: rgb(173,216,230); /* 鼠标滑过一行,动态显示的颜色 */ } .tableStyle td{ border-left: solid 1px rgb(146,208,80); /* 表格的竖线颜色 */ border-top: 1px solid rgb(146,208,80); /* 表格的横线颜色 */ padding: 15px; /* 表格内边框尺寸 */ text-align: center; /* 表格内容显示位置 */ vertical-align: middle; } .tableStyle th{ border-left: solid 1px rgb(146,208,80); border-top: 1px solid rgb(146,208,80); padding: 15px; text-align: center; vertical-align: middle; } .tableStyle th{ padding: 15px; /* 表格标题栏,字体尺寸 */ background-color: rgb(146,208,80); /* 表格标题栏背景颜色 */ /* 标题栏设置渐变色 */ background-image: -webkit-gradient(linear, left top, left bottom, from(#92D050), to(#A2D668)); } </style> </head> <body> <center><h1>TestReport</h1></center><br /> <table class="tableStyle"> <thead> <tr> <th>CaseName</th> <th>TestData</th> <th>ExpectData</th> <th>StartTime</th> <th>SpendTime</th> <th>Result</th> </tr> </thead> ''' endStr = u''' </table> </body> </html> ''' # 拼接成完整html文件 htmlf_file = htmlStr + trData + endStr with open(r"D:/bug_things/selenium/report/DDTByObj.html", "w", encoding='utf-8') as f_obj: f_obj.write(htmlf_file) #f.close()
|
ddt数据驱动
使用ddt进行自动化测试,单元测试框架使用nose,实现如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
| #!/usr/bin/env python3 # -*- coding: utf-8 -*- """ @author: kyle @time: 2018/2/8 14:07 """ from selenium import webdriver from ReportTemplate import htmlTemplate from selenium.common.exceptions import NoSuchElementException from DdtTools.Log import * from DdtTools.MailSend import MailSend from datetime import datetime as dt from nose.tools import assert_true import sys import ddt import time import traceback
@ddt.ddt class TestDdtByJson():
@classmethod def setUpClass(cls): # 只调一次 TestDdtByJson.trStr = ""
def setUp(self): self.browser = webdriver.Chrome() # 存放测试结果状态,失败为fail,成功为pass self.status = None # 数据驱动测试结果的标志,成功置1,失败置0 self.flag = 0
@ddt.file_data("G:/workstation/py_workstation/DataDriverTest/DdtData/test_data_list.json") def test_ddtbyjson(self, value): global start, starttime # 获取当前测试用例名 casename = sys._getframe().f_code.co_name # 确定报告中状态单元格中内容颜色 flagDict = {0: 'red', 1: '#00AC4E'}
url = "https://www.baidu.com" self.browser.get(url) #self.browser.maximize_window() # 将json中测试数据用“||”分隔成测试数据及期望结果 testdata, expectdata = tuple(value.strip().split("||")) self.browser.implicitly_wait(10) try: # 获取当前时间时间戳,用于计算耗时 start = time.time() # 获取当前时间 starttime = time.strftime("%Y-%m-%d %H:%M%S", time.localtime()) # 开始搜索 self.browser.find_element_by_id('kw').send_keys(testdata) self.browser.find_element_by_id('su').click() time.sleep(3) # 断言 assert_true(expectdata in self.browser.page_source) except NoSuchElementException as e: error(u"页面元素不存在:" + str(traceback.print_exc(file=(open("D:/bug_things/selenium/logs/errors/DdtTest.log", 'a'))))) self.status = 'fail' self.flag = 0 except AssertionError as e: error(u'搜索“{0}”,期望“{1}”,失败'.format(testdata, expectdata) + str(traceback.print_exc(file=open("D:/bug_things/selenium/logs/errors/DdtTest.log", 'a')))) self.status = 'fail' self.flag = 0 except Exception as e: error(u"未知错误:" + str(traceback.print_exc(file=open("D:/bug_things/selenium/logs/errors/DdtTest.log", 'a')))) self.status = 'fail' self.flag = 0 else: info(u'搜索“{0}”,期望“{1}”,通过'.format(testdata, expectdata)) self.status = 'pass' self.flag = 1 # 计算消耗时间 # 时间戳相减(10位时间戳单位为s) spends = time.time() - start - 3 # 取两位小数 spendtime = "%.2f" %spends # 报告中添加测试数据 TestDdtByJson.trStr += u''' <tr> <td>{0}</td> <td>{1}</td> <td>{2}</td> <td>{3}</td> <td>{4}</td> <td style="color: {5}">{6}</td> </tr> '''.format(casename, testdata, expectdata, starttime, spendtime, flagDict[self.flag], self.status)
def tearDown(self): self.browser.quit()
@classmethod def tearDownClass(cls): # 写自定义测试报告 htmlTemplate(TestDdtByJson.trStr)
if __name__ == '__main__': os.system("nosetests -s -v {0}".format(__file__)) info(u"测试报告开始发送") report_file = "D:/bug_things/selenium/report/DDTByObj.html" mail_subject = "UnitTest测试报告_{0}".format(dt.now().strftime("%Y%m%d")) mailsend = MailSend(mail_subject, report_file) mailsend.sendMail() info(u"测试报告发送完成")
|
其中涉及到的邮件发送模块和日志模块可以参照以前的博客:
邮件模块
日志配置
其中日志模块增加了对error级别的日志的配置,很简单,和info级别类似,就不多说了。
最终实现效果,测试过程中在控制台以及D:/bug_things/selenium/logs/info/AutoDDT.log
中实时写入info以及error的日志,当出现堆栈错误,写入D:/bug_things/selenium/logs/errors/DdtTest.log
文件中,两个日志文件的写入方式都是append
,测试完成之后邮件发送包含html附件的测试报告到指定邮箱;同时邮件正文中展示包含测试结果的表格,出现fail
状态,可直接前往D:/bug_things/selenium/logs/errors/DdtTest.log
日志中查看具体出错,以及具体出错行。
需要改进的是,D:/bug_things/selenium/logs/errors/DdtTest.log
文件没有明显对各个用例的区分,甚至没有空格行来让显示更明确,还是需要自己去搜索。
后记
现在终于是完成了自动化测试的基本模块,日志和测试报告真的是折腾了…后期自己前端知识丰富之后,还需要优化测试报告。接下来,除了完成从excel和数据库中读取测试数据之外,就真的开始搭建自己的框架了(这几天这牛角尖钻的,解决之后还是挺舒服的~)