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: smtp.126.com
server_username: XXXtest@126.com
server_pwd: XXXXXX
#收件人(列表)
msg_to:
- XXX1@qq.com
- XXX2@126.com
#郵件主題
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、測試報告呈現
測試概要報告
測試執行過程中若有失敗重試時,則報告中會呈現出前一次失敗的結果和原因,同時也會呈現出重試后成功的結果,并且最終的報告結果以最后一次的重試結果為準
測試執行過程有失敗用例時,報告呈現失敗截圖
報告發送至郵件時,郵件標題呈現測試通過與否,或失敗用例數
郵件正文直接顯示本次測試概要報告,直觀顯示出執行用例數,失敗用例數,失敗的用例模塊等結果。
項目實戰演示
總結
以上是生活随笔為你收集整理的python3.7界面设计_基于selenium+Python3.7+yaml+Robot Framework的UI自动化测试框架的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 计算机操作系统_计算机理论(操作系统概念
- 下一篇: 炉石传说源代码_python抓取4399