目录
1.HTML测试报告
HTMLTestRunner 是python标准库unittest单元测试框架的一个扩展,它生成易于使用的HTML测试报告。
下载地址:http://tungwaiyip.info/software/HTMLTestRunner.html
1.1 修改HTMLTestRunner
因为 HTMLTestRunner.py 是基于 python 2 开发的,为了使其支持 python 3 的环境,需要对其中的部分进行修改
第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, ‘\nTimeElapsed: %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
1.2 生成HTML测试报告
下面以 test_baidu.py 为例生成 HTMLTestRunner 测试报告
案例:
from time import sleep
from selenium import webdriver
import unittest
from HTMLTestRunner import HTMLTestRunner
class Baidu(unittest.TestCase):
def setUp(self) -> None:
self.driver = webdriver.Chrome()
self.driver.maximize_window()
self.url = "http://www.baidu.com"
def test_baidu_search(self):
driver = self.driver
driver.get(self.url)
sleep(3)
driver.find_element_by_id("kw").send_keys("HTMLTestRunner")
driver.find_element_by_id("su").click()
sleep(5)
def tearDown(self) -> None:
self.driver.quit()
if __name__ == '__main__':
suite = unittest.TestSuite()
suite.addTest(Baidu("test_baidu_search"))
# 定义报告存放路径
fp = open('./result.html', 'wb')
# 定义测试报告
runner = HTMLTestRunner(stream=fp, title='百度搜索测试报告', description='用例执行情况:')
runner.run(suite)
fp.close()
编写完之后请先不要着急运行,我们得先在当前目录下新建一个 result.html
然后“edit configuration”——这个在前面文章《unittest单元测试框架详解》中第二节关于unittest用例执行的顺序中有提到,避免运行时受到unittest框架的影响
运行完之后,点击查看 result.html :
右击该文件,使用浏览器查看:
1.3 更易读的测试报告
测试报告上面只是展示了一些测试类和测试方法,我们需要对类和方法特殊命名才能提高测试报告的可读性。
这时候python的注释就起作用了。一种叫comment,为普通的注释;一种叫doc string,用于函数、类和方法的描述
我们通过三引号(“”“ ”“” 或 ‘’‘ ’‘’)来添加doc string 类型的注释,这类注释在平时调用的时候不显示,而HTMLTestRunner 可以读取doc string类型的注释
将上面的案例改一下,其他不变:
...
def test_baidu_search(self):
''' 百度搜索测试 '''
driver = self.driver
driver.get(self.url)
sleep(3)
driver.find_element_by_id("kw").send_keys("HTMLTestRunner")
driver.find_element_by_id("su").click()
sleep(5)
...
然后再看 result.html
1.4 测试报告文件名
每次运行测试之前,都要命名一次报告的名称,不然名称相同的话,就会覆盖掉之前的测试报告内容,因此不是很方便。我们可以在报告名称中加入当前时间,这样名称就不会重叠了
import time
from time import sleep
from selenium import webdriver
import unittest
from HTMLTestRunner import HTMLTestRunner
class Baidu(unittest.TestCase):
def setUp(self) -> None:
self.driver = webdriver.Chrome()
self.driver.maximize_window()
self.url = "http://www.baidu.com"
def test_baidu_search(self):
''' 百度搜索测试 '''
driver = self.driver
driver.get(self.url)
sleep(3)
driver.find_element_by_id("kw").send_keys("HTMLTestRunner")
driver.find_element_by_id("su").click()
sleep(5)
def tearDown(self) -> None:
self.driver.quit()
if __name__ == '__main__':
suite = unittest.TestSuite()
suite.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(suite)
fp.close()
执行这份代码不需要自己新建一个HTML文件,这里测试报告是自动生成的
1.5 项目集成测试报告
目前HTMLTestRunner只是针对单个测试文件生成测试报告,我们最终的目的是希望将它集成到统一一个文件runtest.py中,使其作用于整个测试项目:【这也就是说,其他文件中不必再有run的执行语句】
# runtest.py
import unittest
import time
from HTMLTestRunner import HTMLTestRunner
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 = test_dir + '/' + now + 'report.html'
fp = open(filename, 'wb')
runner = HTMLTestRunner(stream=fp, title='项目集成测试报告', description='用例执行情况:')
runner.run(discover)
fp.close()
# test_six.py
import unittest
class TestCount(unittest.TestCase):
def setUp(self) -> None:
print("Test Start")
def test_02(self):
'''单元测试06断言测试'''
a = "hello"
b = "hello world"
self.assertIn(a, b, msg='a is not in b')
def tearDown(self) -> None:
print("Test End")
生成的测试报告如图:
2.自动发邮件功能
我们在自动化测试脚本运行完成之后,邮箱可以收到最新的测试报告结果就是自动发邮件功能。
假设生成的测试报告与很多人有关,每个人都去测试服务器查看就会很麻烦而且不及时。
Python 的 smtplib模块提供了一种很方便的途径用来发送电子邮件,对SMTP协议进行了简单的封装
2.1 发送HTML格式的邮件
Header()方法用来定义邮件标题;
MIMEText()用于定义邮件正文,参数为HTML格式
import smtplib
from email.mime.text import MIMEText
from email.header import Header
# 发送邮箱服务器
smtpserver = 'smtp.qq.com'
# 发送邮箱用户/密码
user = 'XXX@qq.com'
password = 'XXXXXX' # 这个地方不是填写密码,而是授权码
# 发送邮箱
sender = 'XXX@qq.com'
# 接收邮箱
receiver = 'XXX@qq.com'
# 发送邮件主题
subject = 'Python Email Test'
# 编写HTML类型的邮件正文
msg = MIMEText('<html><h3>您好!</h2></html>', 'html', 'utf-8') # MIMEText(文本内容,文本格式,设置编码)
msg['From'] = Header("XXX", 'utf-8') # 发送者
msg['To'] = Header("XX", 'utf-8') # 接收者
msg['Subject'] = Header(subject, 'utf-8') # 邮件主题
# 连接发送邮件
smtp = smtplib.SMTP()
smtp.connect(smtpserver)
smtp.login(user, password)
smtp.sendmail(sender, receiver, msg.as_string())
smtp.quit()
执行结果:
如何获得QQ邮箱授权码?
使用手机发送“配置邮件客户端”到指定号码之后,即可点击“我已发送”按钮,这样授权码就获得了
2.2 发送带附件的邮件
import smtplib
from email.header import Header
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
# 发送邮箱服务器
smtpserver = 'smtp.qq.com'
# 发送邮箱用户及授权码
user = 'XX@qq.com'
password = 'XX'
# 发送邮箱
sender = 'XX@qq.com'
# 接收邮箱
receiver = 'XX@qq.com'
# 创建一个带附件的实例
msg = MIMEMultipart()
msg['From'] = Header("X", 'utf-8')
msg['To'] = Header('X', 'utf-8')
# 邮件主题
subject = 'Python Email Test'
msg['Subject'] = Header(subject, 'utf-8')
# 邮件正文内容
msg.attach(MIMEText('Email附件发送测试', 'plain', 'utf-8'))
# 发送的附件1
sendfile = open('C:/Users/winuser/Desktop/项目测试进程.xlsx', 'rb').read()
att1 = MIMEText(sendfile, 'base64', 'utf-8')
att1['Content-Type'] = 'application/octet-stream'
att1['Content-Disposition'] = 'attachment; filename="test.xlsx"'
msg.attach(att1)
# 发送的附件2
sendfile2 = open('C:/Users/winuser/Desktop/2021App项目进度计划表_0427.xlsx', 'rb').read()
att2 = MIMEText(sendfile2, 'base64', 'utf-8')
att2['Content-Type'] = 'application/octet-stream'
att2.add_header('Content-Disposition', 'attachment', filename='test2.xlsx')
msg.attach(att2)
try:
smtp = smtplib.SMTP()
smtp.connect(smtpserver)
smtp.login(user, password)
smtp.sendmail(sender, receiver, msg.as_string())
print('发送邮件成功')
except smtplib.SMTPException:
print('无法发送邮件')
smtp.quit()
执行结果:
2.3 在HTML中添加图片
import smtplib
from email.header import Header
from email.mime.image import MIMEImage
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
# 发送邮箱服务器
smtpserver = 'smtp.qq.com'
# 发送邮箱用户及授权码
user = 'XX@qq.com'
password = 'XX'
# 发送邮箱
sender = 'XX@qq.com'
# 接收邮箱
receiver = 'XX@qq.com'
# 创建一个带附件的实例
msg = MIMEMultipart()
msg['From'] = Header("X", 'utf-8')
msg['To'] = Header('X', 'utf-8')
subject = 'Python Email Test:在HTML中添加图片'
msg['Subject'] = Header(subject, 'utf-8')
msgAlternative = MIMEMultipart('alternative')
msg.attach(msgAlternative)
mail_msg = """
<h3>Python邮件发送测试</h3>
<p><a herf="http://www.baidu.com">百度搜索连接</a></p>
<p>图片演示:</p>
<p><img src="cid:image1"></p>
<p><img src="cid:image2"></p>
"""
msgAlternative.attach(MIMEText(mail_msg, 'html', 'utf-8'))
sendimage1 = open('C:/Users/winuser/Pictures/null-62d4ba9eb54f96c9.jpg', 'rb')
img = MIMEImage(sendimage1.read())
img.add_header('Content-ID', '<image1>')
msg.attach(img)
sendimage2 = open('C:/Users/winuser/Pictures/null-3728e19a08a1e79.jpg', 'rb')
img2 = MIMEImage(sendimage2.read())
img2.add_header('Content-ID', '<image2>')
msg.attach(img2)
try:
smtp = smtplib.SMTP()
smtp.connect(smtpserver)
smtp.login(user, password)
smtp.sendmail(sender, receiver, msg.as_string())
print('发送邮件成功')
except smtplib.SMTPException:
print('无法发送邮件')
smtp.quit()
执行结果:(图片太大,只截取了一部分)
2.4 查找最新的测试报告
因为测试报告的名称是根据当前时间生成的,所以如何找到最新生成的测试报告是实现发邮件功能的关键
import os
# 定义文件目录
result_dir = 'D:/PycharmProjects/pythonProject/web/test_case'
lists = os.listdir(result_dir)
# 重新按时间对目录下的文件进行排序
lists.sort(key=lambda fn: os.path.getmtime(result_dir + '/' + fn))
print(('最新的文件:' + lists[-1]))
file = os.path.join(result_dir, lists[-1])
print(file)
执行结果:
2.5 整合自动发邮件功能
结合之前的,现在可以将自动发邮件功能集成到自动化测试项目中了。
import os
import smtplib
import time
from HTMLTestRunner import HTMLTestRunner
from email.mime.text import MIMEText
from email.header import Header
import unittest
# 查找测试报告目录,找到最新生成的测试报告文件
def new_report(test_report):
lists = os.listdir(test_report)
lists.sort(key=lambda fn: os.path.getmtime(test_report + "/" + fn))
newfile = os.path.join(test_report, lists[-1])
print(newfile)
return newfile
# 自动发送邮件
def send_email(newfile):
f = open(newfile, 'rb').read()
msg = MIMEText(f, 'html', 'utf-8')
msg['From'] = Header("XX", 'utf-8')
msg['To'] = Header('XX', 'utf-8')
msg['Subject'] = Header('自动化测试报告', 'utf-8')
msg['Content-Type'] = 'application/octet-stream'
msg.add_header('Content-Disposition', 'attachment', filename='Test_Report.html')
try:
smpt = smtplib.SMTP()
smpt.connect('smtp.qq.com')
smpt.login('XX@qq.com', 'XXX')
smpt.sendmail('XX@qq.com', 'XX@qq.com', msg.as_string())
print('发送邮件成功')
except smtplib.SMTPException:
print('无法发送邮件')
smpt.quit()
if __name__ == '__main__':
test_report ='D:/PycharmProjects/pythonProject/web/test_case'
test_dir = "D:/PycharmProjects/pythonProject/web/test_case"
discover = unittest.defaultTestLoader.discover(test_dir, pattern='test_*.py')
now = time.strftime("%Y_%m_%d_%H_%M_%S")
filename = test_report + "/" + now + 'result.html'
fp = open(filename, 'wb')
runner = HTMLTestRunner(stream=fp, title='测试报告', description='用例执行情况:')
runner.run(discover)
fp.close()
newfile = new_report(test_report)
send_email(newfile)
执行结果:
整个程序的执行过程分为三个步骤:
①通过unittest框架的discover()找到匹配的测试用例,由HTMLTestRunner的run()方法执行测试用例并生成最新的测试报告;
②调用new_report()函数找到测试报告目录下最新生成的测试报告,返回测试报告的路径;
③将得到的测试报告路径传给send_email()函数,实现自动发邮件的功能。
整个脚本执行完成后,打开接收邮箱,即可看到最新测试执行的测试报告。