1 框架工具说明
工具 |
说明 |
使用Unittest框架 |
开源自动化测试框架,直接使用 |
批量或指定用例运行 |
Unittest框架可支持此功能 |
log日志 |
使用Python的logging库即可 |
生成HTML测试报告 |
使用BeautifulReport模块可实现此功能 |
用例设计和结果分离 |
PO模式 |
用户登录封装 |
直接把登录功能模块化,使用Unittest框架中的setup,teardown即可 |
定制测试报告模板 |
使用BeautifulReport模块 |
报告多语言 |
使用BeautifulReport模块 |
截图功能 |
使用UIAutomation的CaptureToImage方法 |
2 技术栈说明
技术 |
版本及说明 |
Python |
V3.x(本文为3.7)===编程语言支撑 |
UIAutomation |
控件的识别、定位及操作 |
BeautifulReport |
生成Html测试报告 |
Logging |
Python自带===生成log日志 |
Unittest |
Python自带===自动化测试框架 |
Smtplib |
Python自带===邮件服务 |
email |
Python自带===邮件服务 |
os |
Python自带===系统模块 |
PyCharm |
Community 2020.2汉化版 |
操作系统 |
Windows10旗舰版64位 |
3 框架截图
4 源码解析/common目录
4.1 common/baseinfo.py
# -*- coding:utf-8 -*-
# 作者:虫无涯
# 日期:2023/2/17
# 文件名称:baseInfo.py
# 作用: 封装公用方法-登录模块
import time
import os
import uiautomation # 引入自动化测试工具
import logging # 引入日志模块
from common.creenShot import save_creenshot # 引入截图功能
class InitInfor(object):
"""
封装公用方法-登录模块
"""
def __init__(self):
self.log = logging.getLogger() # 初始化log
os.system()
# 酷狗音乐Test
self.login_name = "xxxx"
self.login_password = "yyyy"
os.startfile(r"D:\KGMusic\KuGou.exe") # 按安装路径打开酷狗音乐
self.kugou = uiautomation.WindowControl(Name="酷狗音乐") # 定位到酷狗音乐窗口
time.sleep(2)
if self.kugou.ButtonControl(Name="最大化").Exists(): # 最大化窗口
self.kugou.ButtonControl(Name="最大化").Click()
else:
pass
def login(self):
self.log.info("=======登录模块=======") # 加入log
self.log.info("登录")
self.kugou.TextControl(Name="登录").Click() # 登录按钮
self.kugou.HyperlinkControl(foundIndex=1).Click() # 点击其它方式登录
save_creenshot(self.kugou)
self.kugou.ButtonControl(Name="关闭").Click() # 关闭登录窗口
# 用户名、密码、登录
# 同样的方法使用qq、手机号、微信等进行登录即可
# 根据自己的项目修改此处的代码进行软件登录即可(后续demo默认不进行登录,只是打开登录窗口然后关闭窗口)
def login_out(self):
time.sleep(0.5)
self.kugou.ButtonControl(Name="关闭").Click() # 关闭窗口退出酷狗音乐,前提是设置酷狗音乐关闭按钮为直接退出程序
self.log.info("关闭窗口,退出酷狗")
if __name__ == "__main__":
b = InitInfor()
b.login()
b.login_out()
4.2 common/creenShot.py
# -*- coding:utf-8 -*-
# 作者:虫无涯
# 日期:2023/2/17
# 文件名称:creenShot.py
# 作用:封装截图功能并调用
import time
def save_creenshot(Windows):
now = time.strftime("%Y-%m-%d-%H_%M_%S", time.localtime(time.time())) # 获取当前时间
pic_path = "../creenshot/"+now+'_screen.png' # 保存截图到指定路径
Windows.CaptureToImage(savePath=pic_path) # 截图功能
4.3 common/logOut.py
# -*- coding:utf-8 -*-
# 作者:虫无涯
# 日期:2023/2/17
# 文件名称:logOut.py
# 作用:封装log日志功能
import logging # 引入日志模块
import time
def log_out(log_dir, name_project):
'''
:log_dir : 日志路径
:name_project : 项目名称=>用于日志命名
:return: 无
'''
now = time.strftime("%Y_%m_%d %H_%M_%S") # 获取当前时间,格式:年月日时分秒
logging.basicConfig(level=logging.INFO,
format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
datefmt='%a, %d %b %Y %H:%M:%S',
filename=log_dir + now + '-' + name_project + '_test_log.log',
filemode='w')
"""
level: 打印日志的级别,INFO:详细; WARNING:警告;ERROR:错误...
format: 为处理程序使用指定的格式字符串;
datefmt:使用特定的时间日期格式;
filename:log日志的文件名称规则;
filemode:文件读写模式。
"""
4.4 common/reportOut.py
# -*- coding:utf-8 -*-
# 作者:虫无涯
# 日期:2023/2/17
# 文件名称:reportOut.py
# 作用:封装测试报告功能
import time
import unittest
from BeautifulReport import BeautifulReport as bf # 引入BeautifulReport报告模板
def report_out(test_dir, report_dir, name_project):
'''
:test_dir: 用例路径
:report_dir : 报告路径
:name_project : 项目名称=>用于报告命名及描述
:return: 无
'''
now = time.strftime("%Y_%m_%d %H_%M_%S")
discover = unittest.defaultTestLoader.discover(test_dir,pattern='test*.py') # 加载测试用例
report_name = now + '-' + name_project + '_test_report.html' # 报告名称
run = bf(discover)
run.report(filename=report_name, report_dir=report_dir, description=U"酷狗音乐UI自动化功能回归测试")
"""
filename:报告名文;
report_dir:测试报告存放路径;
description:报告描述;
"""
4.5 common/sendMail.py
# -*- coding:utf-8 -*-
# 作者:虫无涯
# 日期:2023/2/17
# 文件名称:sendMail.py
# 作用:封装邮件服务模块
import time
import smtplib
import getpass
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
import email
import os
def send_main(file_path, mail_to='xxx@126.com'):
mail_from = 'zzz@126.com'
f = open(file_path, 'rb')
mail_body = f.read()
f.close()
# msg = email.MIMEMultipart.MIMEMultipart()
msg = MIMEMultipart()
# 构造MIMEBase对象做为文件附件内容并附加到根容器
contype = 'application/octet-stream'
maintype, subtype = contype.split('/', 1)
# 读入文件内容并格式化
data = open(file_path, 'rb')
# file_msg = email.MIMEBase.MIMEBase(maintype, subtype)
file_msg = MIMEBase(maintype, subtype)
file_msg.set_payload(data.read())
data.close()
# email.Encoders.encode_base64(file_msg)
encoders.encode_base64(file_msg)
# 设置附件头
basename = os.path.basename(file_path)
file_msg.add_header('Content-Disposition', 'attachment', filename=basename)
msg.attach(file_msg)
print(u'msg 附件添加成功')
msg1 = MIMEText(mail_body, "html", 'utf-8')
msg.attach(msg1)
if isinstance(mail_to, str):
msg['To'] = mail_to
else:
msg['To'] = ','.join(mail_to)
msg['From'] = mail_from
msg['Subject'] = u'酷狗音乐UI自动化功能回归测试'
msg['date'] = time.strftime('%Y-%m-%d-%H_%M_%S')
print(msg['date'])
smtp = smtplib.SMTP()
smtp.connect('smtp.126.com')
smtp.login('yyyyy@126.com', 'mmmmm') # 登录账号和密码(密码为之前申请的授权码)
smtp.sendmail(mail_from, mail_to, msg.as_string())
smtp.quit()
print('email has send out !')
# if __name__=='__main__':
# sendmain('../report/2017-08-18-10_18_57_result.html')