自定义测试报告

解决自动化测试中捕获断言之后,测试报告展示为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和数据库中读取测试数据之外,就真的开始搭建自己的框架了(这几天这牛角尖钻的,解决之后还是挺舒服的~)

文章目录
  1. 自定义报告
  2. ddt数据驱动
  3. 后记
|