700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > python3.7界面设计_基于selenium+Python3.7+yaml+Robot Framework的UI自动化测试框架

python3.7界面设计_基于selenium+Python3.7+yaml+Robot Framework的UI自动化测试框架

时间:2018-12-12 20:46:42

相关推荐

python3.7界面设计_基于selenium+Python3.7+yaml+Robot Framework的UI自动化测试框架

前端自动化测试框架

项目说明

本框架是一套基于selenium+Python3.7+yaml+Robot Framework而设计的数据驱动UI自动化测试框架,Robot Framework 作为执行器,本框架整体特点为:用例与代码分离;用例驱动测试的执行;分层设计、脚本模块化;自动准备测试条件和数据、事后清理;支持失败多次重试、且在每次重试前都会还原一次测试环境,保证重试的成功率;支持邮件呈现测试结果;可灵活挑选项目和用例执行。

框架特点说明

数据驱动

封装一个测试脚本,通过不同的数据来驱动,保证测试覆盖率

用例执行前初始化,执行后释放资源

执行测试数据,并进行结果判断,测试失败或者异常时,会产生相关日志和截图

用例与代码分离

代码中不含有测试用例

测试用例采用robot格式撰写

用例按功能点分类

每个用例都是独立的,不互相依赖也不互相影响

可按项目、模块、测试点挑选执行用例

运行结束后,还原测试环境,清理脏数据

分层设计

操作对象、页面元素、业务逻辑、测试数据相互剥离,灵活调用

封装底层操作组件

按页面封装和分类页面元素

封装基础逻辑,组合业务逻辑实现功能点

脚本模块化

不同功能脚本模块化,各模块间保持独立性和可融合性

封装基础方法,如随机邮箱等

封装通用模块,如文件读写、压缩文件、邮件发送、日志等

模块支持自主开启和关闭

失败多次重试

可自主开启和关闭失败自动重试功能

重试开始在每轮测试结束之后

每次重试前后会初始化环境和还原环境

只重试失败用例

每次重试结束会自动合并重试报告

重试结束会自动合并出总报告

报告可选择自动压缩并邮件发送

测试结束后,也可手动启动失败重试和合并报告

技术栈

selenium

Python3.7

Robot Framework

yaml

AutoItLibrary

logging

SSHLibrary

databaselibrary

环境部署

安装python3.7,并将Python的安装目录添加到系统环境变量的Path路径中

命令行窗口执行pip install -r requirements.txt 安装工程所依赖的库文件

AutoItLibrary安装

安装autoit-v3-setup.exe(V3.3.14.5),安装过程中一定要选x64,不然加载AutoItLibrary还是会是红色

pip install robotframework-autoitlibrary

在Python安装目录(\Python37\Lib\site-packages\win32com\client)下,修改dynamic.py文件,在import pythoncom后,加 pythoncom.CoInitialize() 。(目的是解决在ride中导入AutoItLibrary时,报(-2147221008, '尚未调用 CoInitialize。', None, None)的错误。)

将相关浏览器的驱动,比如谷歌浏览器的驱动chromedriver.exe放在python的安装目录(\Python37)下

将自定义库,比如randomGenerator.py放在python目录(\Python37\Lib\site-packages)下

在Python安装目录(\Python37\Lib\site-packages\robotide\contrib\testrunner)下,修改testrunner.py文件,将'latin1' if IS_WINDOWS修改为'mbcs' if IS_WINDOWS。(目的是解决RIDE控制台中文显示乱码的问题),修改后的内容和位置具体如下:

for _ in myqueuerng:

try:

# DEBUG result += self._queue.get_nowait()

# .decode(utils.SYSTEM_ENCODING, 'replace')

# .decode('UTF-8','ignore')

result += encoding.console_decode(self._queue.get_nowait(),

'mbcs' if IS_WINDOWS

else 'UTF-8')

安装UI元素定位工具(根据实际需要选装)

火狐浏览器插件

Try XPath

xPath Finder

ChroPath

谷歌浏览器插件

ChroPath

框架目录结构图及相关说明

1、代码目录结构图如下

2、目录结构说明

Config ===========> 配置文件

pycode ===========> python公共方法、模块封装,工具类等

rfcode ==========> 存放项目/系统的测试用例、公共配置、界面元素、业务逻辑操作等等

logs ==========> 日志文件

Report ==========> 测试报告

common_Run.py ===========> 测试用例总执行模块

testfile ============> 存放测试过程的操作文件

requirements.txt ============> 相关依赖包文件

run_test.bat =============> 测试启动按钮,测试过程中,若有失败则自动进行失败重试

retry.bat ============> 测试结束后,再次进行失败重试手动启动按钮

代码设计与功能说明

1、定义运行配置文件 config.yml

该文件主要控制测试的执行方式、模块的功能开关、测试用例的筛选、邮件的配置以及日志的配置,具体如下:

config.yml配置信息

---

#待执行的产品项目, Cloud -云项目; rfcode -执行所有的项目

ProductItem: Cloud

#待执行的测试套件(标签), all -所有的测试套件: debug -调试中套件; login -登录功能 ; filter -账号筛选: P1 -一级用例

testSuite: P1

#测试报告标题

testReportTitle: Cloud_Report

#失败重试开关, 0 -关, 1 -开 ,开启后默认重试一次

retry_switch: 0

#失败重试次数

retryTime: 1

#发送测试报告邮件开关, 0 -关, 1 -开

emailSwitch: 1

#邮件配置

#发件邮箱

smtp_server:

server_username: XXXtest@

server_pwd: XXXXXX

#收件人(列表)

msg_to:

- XXX1@

- XXX2@

#邮件主题

msg_subject: '[XX项目][测试环境-develop][jira号][自动化测试报告]'

#日志级别(字典),由高到低: CRITICAL 、 ERROR 、 WARNING 、 INFO 、 DEBUG

log:

file_name: test.log

backup: 5

console_level: DEBUG #控制台日志级别

file_level: DEBUG #文件日志级别

pattern: '%(asctime)s - %(name)s - %(levelname)s - %(message)s'

2、测试用例的设计

测试用例以robot格式的文件保存,平时只需维护测试数据和期望结果,维护成本低。测试用例的数据格式如下:

3、用例执行脚本

按照测试用例,组合业务逻辑,实现功能点测试,以供测试用例循环调用

4、测试执行主程序common_Run.py(收集测试用例,批量执行并生成测试报告,并发送报告到邮件)

# coding: utf-8

import os,sys

import time

from config import BASE_PATH,Config

from global_model.log import logger

from global_model.format_change import formatChange

from email_model.run_sendEmail import sendEailMock

def batch_Call(basePath, product_item, testCase_tag):

'''

首次执行测试:

param robot_testSuite: robot testSuite路径;

param product_item: 执行的待测产品项目;

param testCase_tag: 执行的测试用例标签;

param testCaseReportPath: 测试报告路径;

'''

try:

logger.info(u'=======================首次测试执行开始!正在初始化数据库!=============================')

pybot_result_list = []

output_dir = "-d " + basePath + "/Report/primo_report"

output_xml = "-o output.xml"

output_log = "-l log.html"

output_report = "-r report.html"

productItem = "-s " + product_item

caseTag = "-i " + testCase_tag

pybot_cmd = "pybot " + output_dir + " " + output_xml + " " + output_log + " " + output_report + " " + productItem + " " + caseTag + " " + basePath

pybot_result=os.system(pybot_cmd)

return pybot_result

except Exception as e:

logger.exception(u'首次执行测试失败. %s', e)

finally:

logger.info(u'测试项目根目录为:{0}'.format(basePath))

logger.debug(u'首次执行测试报告输出目录:{0}'.format(output_dir))

logger.info(u'首次执行测试的pybot命令:{0}'.format(pybot_cmd))

logger.info(u'======================首次执行测试已完成!用例失败数为:{0} 个!========================'.format(pybot_result))

def mergeReport(basePath, report_title, match_report, copy_source_match, copy_target_match, merge_report_output):

'''

合并报告:

param testCaseReportPath: 测试报告路径;

param report_title: 合并报告的标题;

return:

'''

try:

logger.info(u'==========================合并测试报告开始!==================================')

output_dir = "-d " + basePath + "/Report/{0}".format(merge_report_output) # 输出合并报告目录

output_xml = "-o output.xml"

output_log = "-l log.html"

output_report = "-r report.html"

# 被合并的报告

merge_report = "--merge " + basePath + "/Report/{0}".format(match_report) + "/output.xml"

title = "--ReportTitle " + report_title

rebot_cmd = r"rebot " + output_dir + " " + output_xml + " " + output_log + " " + output_report + " " + title + " " + merge_report

mergeReport_result = os.system(rebot_cmd)

logger.debug(u'合并报告的结果为:{0}'.format(mergeReport_result))

# 复制截图

testCaseReportPath = basePath + "/Report"

source_files = testCaseReportPath + "/{0}/*.png".format(copy_source_match)

target_dir = testCaseReportPath + "/{0}".format(copy_target_match)

cp_cmd = r"copy " + source_files + " " + target_dir

cp_cmd = cp_cmd.replace("/", "\\")

cope_result = os.system(cp_cmd)

logger.debug(u'复制截图的结果为:{0}'.format(cope_result))

return mergeReport_result

except Exception as e:

logger.exception(u'合并报告异常. %s', e)

finally:

logger.debug(u'输出合并报告目录为:{0}'.format(output_dir))

logger.info(u'合并报告rebot命令:{0}'.format(rebot_cmd))

if mergeReport_result != 0:

logger.info(u'======================合并报告中有失败用例!========================')

else:

logger.info(u'======================没有失败重试的报告需合并,或者合并报告中的用例已全通过!========================')

logger.info(u'复制截图命令为:{0}'.format(cp_cmd))

if cope_result == 0:

logger.info(u'======================截图已成功复制到合并报告中!========================')

else:

logger.info(u'======================报告中没有需要复制的截图!========================')

def cleanLogs(basePath):

'''

删除硬盘中合并前的测试报告:

param testCaseReportPath: 测试报告路径;

return:

'''

try:

logger.info(u'==========================清理磁盘报告开始!==================================')

testCaseReportPath = basePath + "/Report"

primo_report_files = testCaseReportPath + "/primo_report/*"

retry_report_files = testCaseReportPath + "/retry_report/*"

merge_files = testCaseReportPath + "/merge/*"

zip_merges_files = testCaseReportPath + "/zip_merges/*"

retry_times_files = testCaseReportPath + "/retry_times/*"

del_cmd = "del " + primo_report_files + " " + retry_report_files + " " + merge_files + " " + zip_merges_files + " " + retry_times_files

del_cmd = del_cmd.replace("/", "\\")

del_cmd = del_cmd + " " + "/s /q /f"

clean_result = os.system(del_cmd)

except Exception as e:

logger.exception(u'清理磁盘报告异常. %s', e)

finally:

logger.info(u'清理磁盘报告命令为:{0}'.format(del_cmd))

logger.debug(u'清理磁盘报告结果为:{0}'.format(clean_result))

if clean_result == 0:

logger.info(u'======================测试报告清理成功!========================')

else:

logger.info(u'======================测试报告清理失败!========================')

def run_test(basePath, product_item, testCase_tag, report_title, email_switch, smtp_server, server_username, server_pwd, msg_to, msg_subject, retry_switch, retry_time):

'''

失败自动重试:

param robot_testSuite: robot testSuite路径;

param testCase_tag: 执行的测试用例标签;

param testCaseReportPath: 测试报告路径;

param report_title: 合并报告的标题;

'''

#清理环境

cleanLogs(basePath)

#首次执行

run_result = batch_Call(basePath, product_item, testCase_tag)

#失败重试

retryFunction = retry_switch

if retryFunction == 1:

try:

if run_result != 0:

logger.info(u'======================失败用例重试第 1 次!========================')

output_dir = "-d " + basePath + "/Report/retry_report"

retry_xml = "-R " + basePath + "/Report/primo_report/output.xml"

pybot_cmd = "pybot " + retry_xml + " " + output_dir + " " + basePath

logger.info(u'第 1 次失败重试命令为:{0}'.format(pybot_cmd))

retry_result=os.system(pybot_cmd)

logger.info(u'======================失败用例重试第 1 次已完成!用例失败数为:{0} 个!========================'.format(retry_result))

retryTimes = retry_time

n = 2

while (retryTimes >=2 and retry_result != 0):

logger.info(u'======================失败用例重试第 {0} 次!========================'.format(n))

output_dir = "-d " + basePath + "/Report/retry_times"

retry_xml = "-R " + basePath + "/Report/retry_report/output.xml"

pybot_cmd = "pybot " + retry_xml + " " + output_dir + " " + basePath

logger.info(u'第 {0} 次失败重试命令为:{1}'.format(n, pybot_cmd))

retry_result=os.system(pybot_cmd)

logger.info(u'======================失败用例重试第 {0} 次已完成!用例失败数为:{1} 个!========================'.format(n, retry_result))

logger.info(u'======================正在合并重试报告!========================')

merge_report_output = 'retry_report'

match_report = 'retry_*'

copy_source_match = 'retry_times'

copy_target_match = 'retry_report'

mergeReport(basePath, report_title, match_report, copy_source_match, copy_target_match, merge_report_output)

logger.info(u'======================失败用例重试第 {0} 次合并报告已完成!========================'.format(n))

n = n + 1

retryTimes = retryTimes-1

except Exception as e:

logger.exception(u'失败重试异常. %s', e)

else:

logger.info(u'======================本次测试的失败重试功能已关闭!========================')

#合并报告

merge_report_output = 'merge'

match_report = '*_report'

copy_source_match = 'retry_report'

copy_target_match = 'merge'

report_result = mergeReport(basePath, report_title, match_report, copy_source_match, copy_target_match, merge_report_output)

logger.debug(u'======================最终测试结果为: {0} !========================'.format(report_result))

if report_result == 0:

ReportResult = u'测试通过!'

else:

ReportResult = u'测试不通过!失败用例数为:{0} 个'.format(report_result)

#发送report到邮件

emailFunction = email_switch

if emailFunction == 1:

#将字符中的反斜杠转成正斜杠

fileUrl_PATH = basePath.replace('\\','/')

logger.debug(u'基础路径的反斜杠转成正斜杠为:{0}'.format(fileUrl_PATH))

fileUrl='file:///{0}/Report/merge/report.html'.format(fileUrl_PATH)

logger.info(u'html测试报告的url为:{0}'.format(fileUrl))

save_fn=r'{0}\Report\zip_merges\report.png'.format(basePath)

logger.debug(u'转成图片报告后保存的目标路径为:{0}'.format(save_fn))

formatChange_obj = formatChange()

formatChange_obj.html_to_image(fileUrl, save_fn)

email_folder_dir = basePath + "/Report/merge" #待压缩文件夹

logger.debug(u'待压缩文件夹为:{0}'.format(email_folder_dir))

email_target_dir = basePath + "/Report/zip_merges" #压缩文件保存路径

sendEailMock_obj = sendEailMock()

sendEailMock_obj.send_email(email_folder_dir, email_target_dir, smtp_server, server_username, server_pwd, msg_to, msg_subject, ReportResult, save_fn)

else:

logger.info(u'======================本次测试的邮件功能已关闭!========================')

if __name__ == '__main__':

c = Config()

ProductItem = c.get('ProductItem')

testSuite = c.get('testSuite')

testReportTitle = c.get('testReportTitle')

emailSwitch = c.get('emailSwitch')

smtp_server = c.get('smtp_server')

server_username = c.get('server_username')

server_pwd = c.get('server_pwd')

msg_to = c.get('msg_to')

msg_subject = c.get('msg_subject')

retrySwitch = c.get('retry_switch')

retryTime = c.get('retryTime')

run_test(BASE_PATH, ProductItem, testSuite, testReportTitle, emailSwitch, smtp_server, server_username, server_pwd, msg_to, msg_subject, retrySwitch, retryTime)

5、测试报告呈现

测试概要报告

测试执行过程中若有失败重试时,则报告中会呈现出前一次失败的结果和原因,同时也会呈现出重试后成功的结果,并且最终的报告结果以最后一次的重试结果为准

测试执行过程有失败用例时,报告呈现失败截图

报告发送至邮件时,邮件标题呈现测试通过与否,或失败用例数

邮件正文直接显示本次测试概要报告,直观显示出执行用例数,失败用例数,失败的用例模块等结果。

项目实战演示

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。