簡簡單單實現一個Python+Selenium的自動化測試框架

什么是Selenium?

Selenium是一個基于瀏覽器的自動化測試工具,它提供了一種跨平臺、跨瀏覽器的端到端的web自動化解決方案。Selenium主要包括三部分:Selenium IDE、Selenium WebDriver 和Selenium Grid。

  • Selenium IDE:Firefox的一個擴展,它可以進行錄制回放,并把錄制的操作以多種語言(例如java、python等)的形式導出成測試用例。
  • Selenium WebDriver:提供Web自動化所需的API,主要用作瀏覽器控制、頁面元素選擇和調試。不同的瀏覽器需要不同的WebDriver。
  • Selenium Grid:提供了在不同機器的不同瀏覽器上運行selenium測試的能力。

下面我會使用思維導圖目錄結構介紹基礎測試框架,編寫測試用例進行功能測試用例,希望對你的學習有所幫助。

設計思路

框架采用python3 + selenium3 + PO + yaml + ddt + unittest等技術編寫成基礎測試框架,能適應日常測試工作需要。

1、使用Page Object模式將頁面定位和業務操作分開,分離測試對象(元素對象)和測試腳本(用例腳本),一個頁面建一個對象類,提高用例的可維護性;

2、使用yaml管理頁面控件元素數據和測試用例數據。例如元素ID等發生變化時,不需要去修改測試代碼,只需要在對應的頁面元素yaml文件中修改即可;

3、分模塊管理,互不影響,隨時組裝,即拿即用。

測試框架分層設計

把常見的操作和查找封裝成基礎類,不管是什么產品,可直接拿來復用

  • 業務層主要是封裝對象頁面類,一個頁面建一個類,業務層頁面繼承基礎層
  • 用例層針對產品頁面功能進行構造模擬執行測試
  • 框架層提供基礎組件,支撐整個流程執行及功能擴展,給用例層提供各頁面的元素數據、用例測試數據,測試報告輸出等

測試框架目錄結構

如下思維導圖目錄結構介紹:

編寫用例方法

如果對軟件測試、接口測試、自動化測試、性能測試、面試經驗交流。感興趣可以點擊文末小卡片領取,這些資料都是從各個技術網站搜集、整理出來的,希望能幫助到各位!

testinfo:
- id: test_login001
title: 登錄測試
info: 打開抽屜首頁
testcase:
- element_info: login-link-a
find_type: ID
operate_type: click
info: 打開登錄對話框
- element_info: mobile
find_type: ID
operate_type: send_keys
info: 輸入手機號
- element_info: mbpwd
find_type: ID
operate_type: send_keys
info: 輸入密碼
- element_info: //input[@class='keeplogin']
find_type: XPATH
operate_type: click
info: 單擊取消自動登錄單選框
- element_info: //span[text()='登錄']
find_type: XPATH
operate_type: click
info: 單擊登錄按鈕
- element_info: userProNick
find_type: ID
operate_type: perform
info: 鼠標懸停賬戶菜單
- element_info: //a[@class='logout']
find_type: XPATH
operate_type: click
info: 選擇退出
check:
- element_info: //div[@class='box-mobilelogin']
/div[1]/span
find_type: XPATH
info: 檢查輸入手機號或密碼,登錄異常提示
- element_info: userProNick
find_type: ID
info: 成功登錄
- element_info: reg-link-a
find_type: ID
info: 檢查退出登錄是否成功
login.yaml

例如,我們要新增登錄功能測試用例:

首先,只需在testyaml目錄下新增一個頁面對象yaml文件,參考login.yaml格式編寫即可。這些文件是提供給封裝頁面對象類調用并執行定位識別操作。

-
id: test_login001.1
detail : 手機號和密碼為空登錄
screenshot : phone_pawd_empty
data:
phone: ""
password: ""
check :
- 手機號不能為空
-
id: test_login001.2
detail : 手機號為空登錄
screenshot : phone_empty
data :
phone: ""
password : aa
check :
- 手機號不能為空
-
id: test_login001.3
detail : 密碼為空登錄
screenshot : pawd_empty
data :
phone : 13511112222
password: ""
check :
- 密碼不能為空
-
id: test_login001.4
detail : 非法手機號登錄
screenshot : phone_error
data :
phone : abc
password: aa
check :
- 手機號格式不對
-
id: test_login001.5
detail : 手機號或密碼不匹配
screenshot : pawd_error
data :
phone : 13511112222
password: aa
check :
- 賬號密碼錯誤
-
id: test_login001.6
detail : 手機號和密碼正確
screenshot : phone_pawd_success
data :
phone : 13865439800
password: ********
check :
- yingoja
login_data.yamllogin_data.yaml

其次,在testdata目錄下新增一個login_data.yaml文件提供給登錄接口傳參的測試數據,編寫格式參考login_data.yaml文件。

#!/usr/bin/env python
# _*_ coding:utf-8 _*_
__author__ = 'YinJia' 
import os,sys
sys.path.append(os.path.dirname(os.path.dirname
(os.path.dirname(__file__))))
from config import setting
from selenium.webdriver.support.select import Select
from selenium.webdriver.common.action_chains 
import ActionChains
from selenium.webdriver.common.by import By
from public.page_obj.base import Page
from time import sleep
from public.models.GetYaml import getyaml
testData = getyaml(setting.TEST_Element_YAML
+ '/' + 'login.yaml')
class login(Page):
"""
用戶登錄頁面
"""
url = '/'
dig_login_button_loc = (By.ID, testData.
get_elementinfo(0)) def dig_login(self):
"""
首頁登錄
:return:
"""
self.find_element(*self.dig_login_button_loc)
.click() sleep(1)
# 定位器,通過元素屬性定位元素對象
# 手機號輸入框
login_phone_loc = (By.ID,testData.
get_elementinfo(1)) # 密碼輸入框
login_password_loc = (By.ID,testData.
get_elementinfo(2)) # 取消自動登錄
keeplogin_button_loc = (By.XPATH,testData.
get_elementinfo(3)) # 單擊登錄
login_user_loc = (By.XPATH,testData.
get_elementinfo(4)) # 退出登錄
login_exit_loc = (By.ID, testData.
get_elementinfo(5)) # 選擇退出
login_exit_button_loc = (By.XPATH,testData.
get_elementinfo(6))def login_phone(self,phone):
"""
登錄手機號
:param username:
:return:
"""
self.find_element(*self.login_phone_loc).
send_keys(phone)def login_password(self,password):
"""
登錄密碼
:param password:
:return:
"""
self.find_element(*self.login_password_loc).
send_keys(password) def keeplogin(self):
"""
取消單選自動登錄
:return:
"""
self.find_element(*self.keeplogin_button_loc).
click()def login_button(self):
"""
登錄按鈕
:return:
"""
self.find_element(*self.login_user_loc).click()
def login_exit(self):
"""
退出系統
:return:
"""
above = self.find_element(*self.login_exit_loc)
ActionChains(self.driver).move_to_element(above).
perform() sleep(2)
self.find_element(*self.login_exit_button_loc)
.click()def user_login(self,phone,password):
"""
登錄入口
:param username: 用戶名
:param password: 密碼
:return:
"""
self.open()
self.dig_login()
self.login_phone(phone)
self.login_password(password)
sleep(1)
self.keeplogin()
sleep(1)
self.login_button()
sleep(1)
phone_pawd_error_hint_loc = (By.XPATH,testData.
get_CheckElementinfo(0))
user_login_success_loc = (By.ID,testData.
get_CheckElementinfo(1))
exit_login_success_loc = (By.ID,testData.
get_CheckElementinfo(2))
# 手機號或密碼錯誤提示
def phone_pawd_error_hint(self):
return self.find_element(*self.phone_pawd_error_
hint_loc).text# 登錄成功用戶名
def user_login_success_hint(self):
return self.find_element(*self.user_login_
success_loc).text # 退出登錄
def exit_login_success_hint(self):
return self.find_element(*self.exit_login_
success_loc).textloginPage.py

然后,在page_obj目錄下新增一個loginPage.py文件,是用來封裝登錄頁面對象類,執行登錄測試流程操作。

#!/usr/bin/env python
# _*_ coding:utf-8 _*_
__author__ = 'YinJia' 
import os,sys
sys.path.append(os.path.dirname(os.path.
dirname(__file__)))
import unittest,ddt,yaml
from config import setting
from public.models import myunit,screenshot
from public.page_obj.loginPage import login
from public.models.log import Log
try:
f =open(setting.TEST_DATA_YAML + '/' + 'login_data.yaml',encoding='utf-8')
testData = yaml.load(f)
except FileNotFoundError as file:
log = Log()
log.error("文件不存在:{0}".format(file))
@ddt.ddt
class Demo_UI(myunit.MyTest):
"""抽屜新熱榜登錄測試"""
def user_login_verify(self,phone,password):
"""
用戶登錄
:param phone: 手機號
:param password: 密碼
:return:
"""
login(self.driver).user_login(phone,password)
def exit_login_check(self):
"""
退出登錄
:return:
"""
login(self.driver).login_exit()
@ddt.data(*testData)
def test_login(self,datayaml):
"""
登錄測試
:param datayaml: 加載login_data登錄測試數據
:return:
"""
log = Log()
log.info("當前執行測試用例ID-> {0} ; 測試點-> {1}".format(datayaml['id'],datayaml['detail']))
# 調用登錄方法
self.user_login_verify(datayaml['data']['phone'],
datayaml['data']['password'])
po = login(self.driver)
if datayaml['screenshot'] == 'phone_pawd_success':
log.info("檢查點-> {0}".format
(po.user_login_success_hint()))
self.assertEqual(po.user_login_success_hint(), datayaml['check'][0], "成功登錄,返回實際結果是->: {0}".format(po.user_login_success_hint()))
log.info("成功登錄,返回實際結果是->: {0}".format(po.user_login_success_hint()))
screenshot.insert_img(self.driver, datayaml
['screenshot'] + '.jpg')
log.info("-----> 開始執行退出流程操作")
self.exit_login_check()
po_exit = login(self.driver)
log.info("檢查點-> 找到{0}元素,表示退出成功!".format(po_exit.exit_login_success_hint()))
self.assertEqual(po_exit.exit_login_success_hint(),
'注冊',"退出登錄,返回實際結果是->: {0}".format(po_exit.exit_login_success_hint()))
log.info("退出登錄,返回實際結果是->: {0}".format(po_exit.exit_login_success_hint()))
else:
log.info("檢查點-> {0}".format(po.phone
_pawd_error_hint()))
self.assertEqual(po.phone_pawd_error_hint(),
datayaml['check'][0] , "異常登錄,返回實際結果是->: {0}".format(po.phone_pawd_error_hint()))
log.info("異常登錄,返回實際結果是->: {0}".format(po.phone_pawd_error_hint()))
screenshot.insert_img(self.driver,datayaml
['screenshot'] + '.jpg')
if __name__=='__main__':
unittest.main()
login_sta.py

最后,在testcase目錄下創建測試用例文件login_sta.py,采用ddt數據驅動讀取yaml測試數據文件

綜上所述,編寫用例方法只需要按以上四個步驟創建->編寫即可。

執行如下主程序,可看輸出的實際結果。

#!/usr/bin/env python
# _*_ coding:utf-8 _*_
__author__ = 'YinJia' import os,sys
sys.path.append(os.path.dirname(__file__))
from config import setting
import unittest,time
from package.HTMLTestRunner import HTMLTestRunner
from public.models.newReport import new_report
from public.models.sendmail import send_mail
# 測試報告存放文件夾,如不存在,則自動創建
一個report目錄 if not os.path.exists(setting.TEST_REPORT):os.makedirs
(setting.TEST_REPORT + '/' + "screenshot")
def add_case(test_path=setting.TEST_DIR):
"""加載所有的測試用例"""
discover = unittest.defaultTestLoader.discover
(test_path, pattern='*_sta.py')
return discover
def run_case(all_case,result_path=setting.TEST_REPORT):
"""執行所有的測試用例"""
now = time.strftime("%Y-%m-%d %H_%M_%S")
filename = result_path + '/' + now + 'result.html'
fp = open(filename,'wb')
runner = HTMLTestRunner(stream=fp,title='
抽屜新熱榜UI自動化測試報告',
description='環境:windows 7 瀏覽器:chrome',
tester='Jason')
runner.run(all_case)
fp.close()
report = new_report(setting.TEST_REPORT)
#調用模塊生成最新的報告
send_mail(report) #調用發送郵件模塊
if __name__ =="__main__":
cases = add_case()
run_case(cases)

測試結果展示

HTML報告日志

HTML報告點擊截圖,彈出截圖?

測試報告通過的日志

自動截圖存放指定的目錄

郵件測試報告

同時,在這我為大家準備了一份軟件測試視頻教程(含面試、接口、自動化、性能測試等),就在下方,需要的可以直接去觀看。

【2025最新版】字節大牛講的最全最細的自動化測試全套教程!永久白嫖,拿走不謝,全程干貨無廢話!逼自己15天內學完,從軟件測試基礎到項目實戰一套全通關!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/78955.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/78955.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/78955.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Java設計模式之中介者模式:從入門到架構級實踐

一、什么是中介者模式? 中介者模式(Mediator Pattern)是一種行為型設計模式,其核心思想是通過引入一個中介對象來封裝多個對象之間的交互關系。這種模式將原本復雜的網狀通信結構轉換為星型結構,類似于現實生活中的機…

Trinity三位一體開源程序是可解釋的 AI 分析工具和 3D 可視化

一、軟件介紹 文末提供源碼和程序下載學習 Trinity三位一體開源程序是可解釋的 AI 分析工具和 3D 可視化。Trinity 提供性能分析和 XAI 工具,非常適合深度學習系統或其他執行復雜分類或解碼的模型。 二、軟件作用和特征 Trinity 通過結合具有超維感知能力的不同交…

LeetCode 熱題 100_單詞拆分(86_139_中等_C++)(動態規劃)

LeetCode 熱題 100_單詞拆分(86_139) 題目描述:輸入輸出樣例:題解:解題思路:思路一(動態規劃): 代碼實現代碼實現(思路一(動態規劃)&a…

VM虛擬機安裝及Ubuntu安裝配置

VM虛擬機安裝及Ubuntu安裝配置 1、VM虛擬機安裝2、創建虛擬機3、Ubuntu系統安裝4、編譯環境配置4.1 、Ubuntu和 Windows文件互傳 文件互傳4.1.1、 開啟Ubunt下的FTP服務 4.2、 Ubuntu下NFS和SSH服務開啟4.2.1、 NFS服務開啟4.2.2、 SSH服務開啟 4.3、 交叉編譯器安裝4.3.1 安裝…

【KWDB 創作者計劃】_產品技術解讀_1

【KWDB 創作者計劃】_產品技術解讀_1 一、存儲引擎:高性能混合存儲架構1. 存儲模型設計2. 存儲壓縮與編碼3. 持久化策略二、KWDB 組件源碼解析1. 核心模塊分層架構2. 關鍵組件源碼剖析三、KWDB 特性代碼通讀1. 實時分析能力(Real-Time OLAP)2. 混合負載隔離(HTAP)3. 智能索…

高速電路中的電阻、電容的選型及應用

2.1 電阻的應用 2.1.1 與電阻相關的經典案例 如果說芯片是電路的骨架,那么電阻就是在芯片之間起連接作用的關節。電阻的阻值、布放位置等,對設計的成功起著至關重要的作用。 【案例2.1】串聯電阻過大,導致板間告警失敗 某產品由業務板和主…

springBoot接入文心一言

文章目錄 效果接入步驟項目接入配置類:WenXinYiYan前端vue代碼js代碼 后端mapper層service層controller層 測試代碼 效果 先來看一下最后實現的效果 (1)未點擊前的功能頁面 (2)點擊后的頁面 (3&#xff…

css解決邊框四個角有顏色

效果 html <div class"gradient-corner">2021年</div>css background:/* 左上角橫線 */linear-gradient(90deg, rgb(5, 150, 247) 9px, transparent 0) 0 0,/* 左上角豎線 */linear-gradient(0deg, rgb(5, 150, 247) 9px, transparent 0) 0 0,/* 右上…

自動化三維掃描:CASAIM外觀尺寸智能檢測

制造業向智能化、數字化加速轉型&#xff0c;傳統檢測方式因效率低、精度差、數據斷層等問題&#xff0c;已難以滿足現代工業對精密測量與實時質控的需求。CASAIM依托前沿技術實力&#xff0c;以自動化三維掃描為核心&#xff0c;為工業檢測提供了從數據采集到智能分析的全流程…

突破亞馬遜壁壘,Web Unlocker API 助您輕松獲取數據

目錄 一、Web Unlocker API簡介二、開始使用Web Unlocker API1、首先進入控制臺頁面&#xff0c;點擊左側第一個tab鍵“代理 & 抓取基礎設施”&#xff0c;找到“網頁解鎖器”&#xff0c;開始使用。2、進入網頁解鎖器頁面后&#xff0c;填寫通道名稱&#xff0c;添加簡短描…

【力扣05】最長回文子串

0. 引言 ●子串(substring&#xff09;&#xff1a;原始字符串的一個連續子集; ●子序列&#xff08;subsequence&#xff09;&#xff1a;原始字符串的一個子集。 1. 什么叫回文串&#xff1f; 如果一個字符串正著讀和反著讀是一樣的&#xff0c;那它就是回文串。[1] 例如&…

統計銷量前十的訂單

傳入參數&#xff1a; 傳入begin和end兩個時間 返回參數 返回nameList和numberList兩個String類型的列表 controller層 GetMapping("/top10")public Result<SalesTop10ReportVO> top10(DateTimeFormat(pattern "yyyy-MM-dd") LocalDate begin,Dat…

【HDFS入門】HDFS核心組件Secondary NameNode角色職責與運行機制解析

目錄 1 Secondary NameNode的角色定位與常見誤解 2 核心職責詳解 2.1 核心功能職責 2.2 與NameNode的協作關系 3 運行機制深度剖析 3.1 檢查點觸發機制 3.2 元數據合并流程 4 與Hadoop 2.0 HA架構的對比 5 配置調優指南 5.1 關鍵配置參數 5.2 性能優化建議 6 實踐應…

MySQL存儲引擎:存儲什么意思?引擎什么意思?存儲引擎是什么?在MySQL中有什么作用?

MySQL存儲引擎詳解 一、術語解析 “存儲”與“引擎”的漢語詞典解釋 1. 存儲&#xff08;chǔ cn&#xff09; 漢語詞典釋義&#xff1a; ? 動詞&#xff1a; ? 存放、保存&#xff08;將物品或信息放置在特定地方&#xff0c;以便后續使用&#xff09;。 ? 例&#xff…

測試第三課-------自動化測試相關

作者前言 &#x1f382; ??????&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f382; ?&#x1f382; 作者介紹&#xff1a; &#x1f382;&#x1f382; &#x1f382; &#x1f389;&#x1f389;&#x1f389…

Hive null safe的用法

總結: null safe 是用<> 代表比較&#xff0c;而不是用 。null <> null 返回 true&#xff0c; 而 null null 代表 false。 NULL 和任意字符比較都返回 NULL&#xff0c;而不是 true 或者 false。如 SELECT 1 1, NULL NULL, 1 NULL;輸出 true NULL NULL如果我…

LINUX基礎 [四] - Linux工具

目錄 軟件包管理器yum Linux開發工具vim vim的基本概念 vim的三種常用模式 vim的簡單配置 vim常用模式的基本操作 命令模式 底行模式 處理vim打開文件報錯的問題 Linux編譯器-gcc/g使用 為什么我們可以用C/C做開發呢&#xff1f; 預處理&#xff08;進行宏替換&#x…

RocketMQ 03

今天是2025/04/14 21:58 day 20 總路線請移步主頁Java大綱相關文章 今天進行RocketMQ 6,7,8 個模塊的歸納 最近在忙畢設&#xff0c;更新有點慢&#xff0c;見諒 首先是RocketMQ 的相關內容概括的思維導圖 6. 安全機制 6.1 ACL 訪問控制 核心功能 權限分級&#xff1a;通過…

深入理解瀏覽器的 Cookie:全面解析與實踐指南

在現代 Web 開發中&#xff0c;Cookie 扮演著舉足輕重的角色。它不僅用于管理用戶會話、記錄用戶偏好&#xff0c;還在行為追蹤、廣告投放以及安全防護等諸多方面發揮著重要作用。隨著互聯網應用場景的不斷豐富&#xff0c;Cookie 的使用和管理也日趨復雜&#xff0c;如何在保障…

在企業級部署中如何優化NVIDIA GPU和容器環境配置:最佳實踐與常見誤區20250414

在企業級部署中如何優化NVIDIA GPU和容器環境配置&#xff1a;最佳實踐與常見誤區 引言 隨著AI和深度學習技術的迅速發展&#xff0c;企業對GPU加速計算的需求愈加迫切。在此過程中&#xff0c;如何高效地配置宿主機與容器化環境&#xff0c;特別是利用NVIDIA GPU和相關工具&…