組件庫UI自動化

一、背景

  • 背景:
    • 組件庫全局改動場景多,組件之間耦合場景多–時常需要全場景回歸
    • 組件庫demo有200多個,手動全局回歸耗時耗力
    • 細微偏差純視覺無法辨別
  • 可行性分析:
    • 組件庫功能占比
      • L1(視覺層):圖片對比確保整體視覺一致性(占比40%)
      • L2(屬性層):傳統斷言驗證核心功能(占比50%)
      • L3(交互層):行為模擬驗證動態邏輯(占比10%)
    • 時間成本分析
      • 視覺層:5個工作日可實現所有demo截圖對比,無需補充場景,單月用例維護時間只需2個工作日
      • 屬性層:無法一步實現所有demo屬性測試,單月用例維護/場景維護或大于5個工作日
    • 技術實現可行性
      • 視覺層:python 可實現,selenium可實現瀏覽器驅動和頁面截圖,PIL可實現圖片對比
      • 屬性層:可實現架構多,但目前沒有找到快速獲取組件屬性的方式和屬性校準的方式
  • 應用場景:
    • 視覺密集型組件(圖表/靜態圖等)
    • 回歸測試中視覺回歸防御
  • 整體思路:
    • 找到組件庫demo對應URL規則批量抓取
    • 截圖保存到本地
    • PIL工具對比輸出差異
      二、操作步驟
      2.1 開發前的準備工作
      準備工作一
  • Selenium驅動安裝
    準備工作二
  • demo目錄結構分析
    2.2 開發
    代碼邏輯:
    爬取所有路徑下demo名稱,數組形式輸出
import osdef list_directories(path):"""列出指定路徑下的所有直接子目錄返回格式:目錄名稱列表(按字母順序排序)"""try:# 獲取路徑下所有條目entries = os.listdir(path)# 過濾出目錄并排序directories = sorted([entry for entry in entriesif os.path.isdir(os.path.join(path, entry))])return directoriesexcept FileNotFoundError:print(f"錯誤:路徑不存在 - {path}")return []except PermissionError:print(f"錯誤:沒有訪問權限 - {path}")return []except Exception as e:print(f"未知錯誤:{str(e)}")return []if __name__ == "__main__":drislist = []target_path = "/Users/forest/Desktop/"dirs = list_directories(target_path)if dirs:print(f"在 {target_path} 下找到 {len(dirs)} 個目錄:")for idx, directory in enumerate(dirs, 1):print(f"{idx}. {directory}")target_path1 = "/Users/forest/Desktop/"+directory+"/demo"dirs1 = list_directories(target_path1)if dirs1:for idx, directory1 in enumerate(dirs1, 1):print(f"{idx}. {directory1}")drislist.append(directory+"-"+directory1)else:print("未找到任何目錄或路徑無效")# 測試用例print(drislist)test_path = "/Users/forest/Desktop/"

圖片對比compare_images方法


from PIL import Image, ImageChops
from datetime import datetimedef compare_images(image1_path, image2_path, output_diff_path=None):# 打開兩張圖片img1 = Image.open(image1_path)img2 = Image.open(image2_path)# 確保圖片尺寸相同if img1.size != img2.size:raise ValueError("圖片尺寸不一致,無法對比!")# 計算差異diff = ImageChops.difference(img1, img2)if diff.getbbox() is None:print("圖片完全一致!")return 0.0  # 差異百分比# 統計差異像素pixels = list(diff.getdata())diff_pixels = sum(1 for pixel in pixels if pixel != (0, 0, 0, 0))total_pixels = len(pixels)diff_percentage = (diff_pixels / total_pixels) * 100# 保存差異圖(可選)if output_diff_path:diff.save(output_diff_path)print(f"差異圖已保存至: {output_diff_path}")print(f"圖片差異百分比: {diff_percentage:.2f}%")return diff_percentage

主方法

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import time
from datetime import datetimefrom app.diff.diff import compare_images
from app.diff.moduleDemoData import moduleDemoDatasindex = 0now = datetime.now()
date_str1 = now.strftime("%Y-%m-%d")
date_str ='2025-08-11'
print(date_str)
# 配置 Chrome 選項(無頭模式)
chrome_options = Options()
chrome_options.add_argument("--headless")  # 無界面模式
chrome_options.add_argument("--disable-gpu")
chrome_options.add_argument("--window-size=1920,1080")  # 截圖尺寸# 啟動瀏覽器driver = webdriver.Chrome(options=chrome_options)output_diff_path = '/Users/forest/PycharmProjects/static'# 等待頁面加載(可根據需要調整)
passModuleDemoData = []
localModuleDemoData = []
for moduleDemoData in moduleDemoDatas:passUrl = "http://localhost:4600/v2/~examplesh-"+moduleDemoData+"-example"driver.get(passUrl)time.sleep(5)
# 截圖并保存passScreenshot_path = "/Users/forest/pass"+moduleDemoData+".png"driver.save_screenshot(passScreenshot_path)print(f"截圖已保存至: {passScreenshot_path}")passModuleDemoData.append(passScreenshot_path)for moduleDemoData in moduleDemoDatas:localUrl = "-"+moduleDemoData+"-example"driver.get(localUrl)time.sleep(5)# 截圖并保存localScreenshot_path = "moduleDemoData+".png"driver.save_screenshot(localScreenshot_path)print(f"截圖已保存至: {localScreenshot_path}")localModuleDemoData.append(localScreenshot_path)for moduleDemoData in moduleDemoDatas:print(compare_images(passModuleDemoData[index], localModuleDemoData[index]))if compare_images(passModuleDemoData[index], localModuleDemoData[index]) > 0:compare_images(passModuleDemoData[index], localModuleDemoData[index], output_diff_path+"error"+date_str1+moduleDemoData+".png")print("error"+moduleDemoData)index += 1
# 關閉瀏覽器
driver.quit()

參數列表:羅列代碼中涉及的參數和含義
參數 含義
compare_images :return 0無差異

暫時無法在飛書文檔外展示此內容
三、總結
總結本次技術應用中可積累的代碼和經驗
技術經驗
有待提升

  • 可分批運行
  • …版本發現bug數
  • 樣式隔離節省回歸時間30%以上
  • 滾動截圖

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

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

相關文章

面試題:JVM與G1要點總結

一.Java內存區域 1.運行時數據區的介紹 2.站在線程的角度看Java內存區域 3.深入分析堆和棧的區別 4.方法的出入棧和棧上分配、逃逸分析及TLAB 5.虛擬機中的對象創建步驟 6.對象的內存布局 1.運行時數據區的介紹 運行時數據區的類型:程序計數器、Java虛擬機棧、本地方…

車輛安全供電系統開發原則和實踐

摘要在汽車行業中,安全應用的重要性在不斷提升,例如受車輛自動化發展以及機械備用系統重要性降低的影響。為應對這些趨勢,安全相關的電氣和 / 或電子系統(E/E 系統)的電源輸入必須由供電系統來保障,這使得功…

WebSocket客戶端庫:websocket-fruge365

🚀 從零開始打造一個WebSocket客戶端庫:websocket-fruge365 📖 前言 在現代Web開發中,實時通信已經成為不可或缺的功能。無論是聊天應用、實時數據監控,還是在線協作工具,WebSocket都扮演著重要角色。然而…

rocketmq批量執行跑批任務報錯

rocketmq批量執行跑批任務,報下面的錯誤,怎么處理一下呢?是修改配置還是修改代碼還是? org.apache.rocketmq.client.exception.MQBrokerException: CODE: 215 DESC: [FLOW]client has exhausted the send quota for the current …

大語言模型(LLM)簡介與應用分享

1. 什么是大語言模型(LLM) 大語言模型(Large Language Model,簡稱 LLM)是基于 深度學習 和 海量文本數據 訓練而成的人工智能模型。 采用 Transformer 架構參數規模巨大(數十億到數千億)能夠 理…

【算法筆記】選擇排序、插入排序、冒泡排序、二分查找問題

算法的筆記,直接上代碼,思路和問題這些,都在代碼注釋上面 1、工具類 為了生成測試代碼和比較器,專門寫了一個數組工具類,代碼如下: /*** 數組工具類*/ public class ArrUtil {/*** 生成隨機數組* 長度是[0,…

行業分享丨基于SimSolid的大型汽車連續沖壓模具剛度分析

*本文投稿自機械零部件制造業用戶 汽車連續模具的剛度直接決定了沖壓件質量(尺寸精度、表面缺陷)與模具壽命。傳統有限元分析(FEA)在面對大型復雜模具裝配體時,存在網格劃分困難、計算資源消耗大、周期長等瓶頸。本文以…

用AI生成的html頁面設計放到到Axure上實現再改造的方法

要將 AI 生成的 HTML 原型導入 Axure,該方法的核心邏輯是以 Figma 為 “中間橋梁”(因 Axure 無法直接讀取 HTML,需通過 Figma 轉換格式),分 3 步即可完成,以下是詳細操作指南(含每步目標、具體…

從入門到實戰:Linux sed命令全攻略,文本處理效率翻倍

從入門到實戰:Linux sed命令全攻略,文本處理效率翻倍 文章目錄從入門到實戰:Linux sed命令全攻略,文本處理效率翻倍一、認識sed:什么是流編輯器?二、吃透sed工作原理:為什么它能高效處理文本&am…

TIOBE 8月編程語言榜深度解析:Python占比突破26%,Perl成最大黑馬

根據TIOBE最新發布的2025年8月編程語言排行榜,一場靜默的技術變革正在上演:Python以26.14%的占比首次突破26%大關,連續12個月穩居榜首。這一數據不僅刷新了Python自身的歷史紀錄,更成為TIOBE指數自2001年創立以來的最高單語言占比…

從發現到恢復,看瑞數信息如何構建“抗毀重構”實戰路徑

在信息化社會,“韌性”“彈性”這些詞匯常被用來形容系統抵御和應對風險的能力,但對于身處關鍵基礎設施行業的運營者來說,這些概念往往過于抽象,難以直接指導實踐。 相比之下,“抗毀重構”更具畫面感。它不僅是一個管理…

深入理解 jemalloc:從內存分配機制到技術選型

在高性能服務(如數據庫、緩存、JVM)的底層優化中,內存分配效率直接影響系統整體性能。本文將從操作系統底層的malloc機制切入,詳解 jemalloc 的設計理念、開源應用場景、實戰案例,技術選型分析 一、操作系統底層的內存…

websoket使用記錄

1.項目使用記錄1.醫療項目中渲染回收柜溫濕度,需要實時更新2.回收柜安瓿回收和余液回收時,需要前端發送指令給回收柜,比如開門、關門等。還需要收到回收柜結果,比如回收的藥品信息等。我項目中用的是瀏覽器自帶的websoket&#xf…

DevOps篇之通過GitLab CI 流水線實現k8s集群中helm應用發布

一. 設計思路 構建一個 GitLab CI 流水線,并且要集成到 K8s 集群中的 Helm 應用發布流程。首先,需要了解 GitLab CI 的基本結構,比如.gitlab-ci.yml 文件的配置,包括 stages、jobs、變量設置等。然后,結合之前討論的 H…

詳盡 | Deeplabv3+結構理解

https://arxiv.org/pdf/1802.02611.pdf https://link.springer.com/chapter/10.1007/978-3-319-10578-9_23 目錄 Deeplabv3 Encoder部分 Decoder部分 補充摘要 SPP 空間金字塔池化層模塊 Dilated/Atrous Conv 空洞卷積 Deeplabv3 deeplab-v3是語義分割網絡,組…

【51單片機】【protues仿真】基于51單片機音樂盒(8首歌曲)系統

目錄 一、主要功能 二、使用步驟 三、硬件資源 四、軟件設計 五、實驗現象 一、主要功能 1、數碼管顯示當前歌曲序號 2、按鍵切換歌曲和播放暫停? 3、內置8首音樂 二、使用步驟 基于51單片機的音樂盒是一種能夠存儲和播放多首歌曲的電子設備,通過定時器產…

@ZooKeeper 詳細介紹部署與使用詳細指南

文章目錄 **ZooKeeper 詳細介紹、部署與使用** 1. 概述 & 核心介紹 1.1 什么是 ZooKeeper? 1.2 核心特性 1.3 核心概念 1.4 典型應用場景 2. 部署 (以 3 節點集群為例) 2.1 環境準備 2.2 安裝步驟 (在所有節點執行) 2.3 啟動與停止集群 2.4 防火墻配置 (如果開啟) 3. 基本…

騰訊Hunyuan-MT-7B翻譯模型完全指南:2025年開源AI翻譯的新標桿

🎯 核心要點 (TL;DR) 突破性成就:騰訊混元MT-7B在WMT25全球翻譯競賽中獲得30/31項第一名雙模型架構:Hunyuan-MT-7B基礎翻譯模型 Hunyuan-MT-Chimera-7B集成優化模型廣泛語言支持:支持33種語言互譯,包括5種中國少數民…

Web 集群高可用全方案:Keepalived+LVS (DR) 負載均衡 + Apache 服務 + NFS 共享存儲搭建指南

文章目錄Keepalived LVS(DR) Apache NFS項目背景業務場景與核心需求傳統架構的痛點與局限技術方案的選型邏輯項目價值與預期目標項目實踐項目環境基礎配置配置 router配置免密登錄-可選配置 nfs配置 web配置 LVS-RS配置 HA 和 LVS-DS配置 ha1配置 ha2測…

Prometheus監控預警系統深度解析:架構、優劣、成本與競品

目錄 一、Prometheus是什么?核心定位與架構 二、競品分析(Prometheus vs. Zabbix vs. Nagios vs. Commercial SaaS) 三、部署成本分析 四、服務器資源消耗分析 五、給您的最終建議 一、Prometheus是什么?核心定位與架構 Prom…