pytest并發測試,資源問題導致用例失敗解決辦法

  • 遇見的問題:
    測試用例使用thrift資源和redis資源,單獨運行case沒有問題,但是使用并發pytest-xdist(-n 10 和 --dist=loadscope)運行失敗

  • 原因:
    測試用例間存在共享資源競爭(如 Redis、Thrift 連接)和測試類狀態未隔離

  • 解決辦法:
    原來的測試前置是通過傳統的setup來實現初始化,會導致資源共享

def setup(self):self.check = common_check.CommonCheck()self.req = common_req.CommonReq()self.driverId = int(''.join(str(random.randint(0, 9)) for _ in range(10)))self.passengerId_one = int(''.join(str(random.randint(0, 9)) for _ in range(10)))self.passengerId_two = int(''.join(str(random.randint(0, 9)) for _ in range(10)))self.passengerId_three = int(''.join(str(random.randint(0, 9)) for _ in range(10)))self.orderId = str(int(''.join(str(random.randint(0, 9)) for _ in range(10))))self.orderId_two = str(int(self.orderId) + 1)self.orderId_three =  str(int(self.orderId)+ 2)self.travel_id = int(''.join(str(random.randint(0, 9)) for _ in range(10)))# self.redish = redis.StrictRedis(host=globalVar.g_fusion_ip, port=globalVar.g_fusion_port,password=globalVar.g_fusion_password, username=globalVar.g_fusion_username, db=0)self.redish = redis.StrictRedis(host=globalVar.g_redis_ip, port=globalVar.g_redis_port, db=0)try:transport = TSocket.TSocket(globalVar.crm_ip, globalVar.crm_port)transport.setTimeout(10000)transport = TTransport.TFramedTransport(transport)protocol = TBinaryProtocol.TBinaryProtocol(transport)self.client = Client(protocol)transport.open()self.trans = transportexcept Thrift.TException as tx:print('%s' % (tx.message))except Exception as ex:print('%s' % (ex.message))

現在通過fixture,為每個用例創建獨立資源 + 自動清理」,實現了用例間的完全隔離,從根本上避免了并發沖突

@pytest.fixture(autouse=True)def setup_isolated(self):self.test_uuid = str(uuid.uuid4())  # 測試用例唯一IDself.driverId = self._generate_unique_id()self.passengerId_one = self._generate_unique_id()self.passengerId_two = self._generate_unique_id()self.passengerId_three = self._generate_unique_id()self.orderId = str(self._generate_unique_id())self.orderId_two = str(int(self.orderId) + 1)self.orderId_three = str(int(self.orderId) + 2)self.travel_id = self._generate_unique_id()# 2. 初始化工具類(無狀態,可安全復用)self.check = common_check.CommonCheck()self.req = common_req.CommonReq()# 3. 初始化 Redis 連接(每個用例獨立連接,避免共享)self.redish = redis.StrictRedis(host=globalVar.g_redis_ip,port=globalVar.g_redis_port,db=0,decode_responses=True  # 避免 bytes/str 類型混亂)# 4. 初始化 Thrift 客戶端(每個用例獨立連接,避免共享)self.transport = Noneself.client = Nonetry:self.transport = TSocket.TSocket(globalVar.crm_ip, globalVar.crm_port)self.transport.setTimeout(10000)self.transport = TTransport.TFramedTransport(self.transport)protocol = TBinaryProtocol.TBinaryProtocol(self.transport)self.client = Client(protocol)self.transport.open()except Thrift.TException as tx:pytest.fail("Thrift 連接初始化失敗:",tx.message)except Exception as ex:pytest.fail("未知錯誤: ",ex.message)# 5. 用例執行前的鉤子(yield 前為 setup,后為 teardown)yield# 6. 用例結束后清理資源(避免連接泄漏)if self.transport and self.transport.isOpen():self.transport.close()self.redish.close()  # 關閉 Redis 連接@contextmanagerdef redis_lock(self, key, timeout=5):"""Redis 分布式鎖(解決多進程共享資源競爭)"""lock_key = "lock:{key}"lock_acquired = Falsetry:# 嘗試獲取鎖(NX=不存在才設置,PX=過期時間毫秒)lock_acquired = self.redish.set(lock_key, self.test_uuid, nx=True, px=timeout * 1000)if not lock_acquired:pytest.fail("獲取 Redis 鎖失敗(key: )" + lock_key + ",可能存在并發競爭")yield  # 鎖內邏輯執行區finally:# 釋放鎖(僅刪除自己持有的鎖,避免誤刪其他進程的鎖)if lock_acquired:current_lock_val = self.redish.get(lock_key)if current_lock_val == self.test_uuid:self.redish.delete(lock_key)

生成安全的key:UUID前10位 + 時間戳,避免碰撞

 def _generate_unique_id(self):"""生成并發安全的唯一ID(UUID前10位 + 時間戳,避免碰撞)"""timestamp = int(time.time() * 1000)  # 毫秒級時間戳(確保時序唯一)uuid_part = int(str(uuid.uuid4()).replace('-', '')[:8], 16)  # UUID前8位(16進制轉10進制)return int("{}{}".format(timestamp, uuid_part)[:10])  # 截取10位,符合原ID長度

@contextmanager 是 Python 標準庫 contextlib 模塊中的一個裝飾器,用于快速定義上下文管理器(Context Manager)。它的核心作用是簡化「資源獲取 - 使用 - 釋放」的流程,確保資源(如文件、數據庫連接、鎖等)在使用后被正確釋放,即使過程中發生異常

  • redis枷鎖
@contextmanagerdef redis_lock(self, key, timeout=5):"""Redis 分布式鎖(解決多進程共享資源競爭)"""lock_key = "lock:{key}"lock_acquired = Falsetry:# 嘗試獲取鎖(NX=不存在才設置,PX=過期時間毫秒)lock_acquired = self.redish.set(lock_key, self.test_uuid, nx=True, px=timeout * 1000)if not lock_acquired:pytest.fail("獲取 Redis 鎖失敗(key: )" + lock_key + ",可能存在并發競爭")yield  # 鎖內邏輯執行區finally:# 釋放鎖(僅刪除自己持有的鎖,避免誤刪其他進程的鎖)if lock_acquired:current_lock_val = self.redish.get(lock_key)if current_lock_val == self.test_uuid:self.redish.delete(lock_key)

在用到redis非刪除操作的地方,先判斷redis鎖是否釋放
在這里插入圖片描述

  • 需要導入的模塊:
    import uuid
    from contextlib import contextmanager

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

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

相關文章

C 盤又滿了?6 個「零風險清理法」+5 款神器,讓電腦瞬間多出 100GB 空間

你是否遇到過這樣的場景:正在趕工寫報告,突然彈出「C 盤存儲空間不足」的警告;想安裝新軟件,卻因為 C 盤爆紅而反復失敗;甚至電腦越來越卡,開機要等 5 分鐘,打開文件夾都要轉圈…… 作為系統盤…

Android 項目:畫圖白板APP開發(四)——筆鋒(單 Path)

上一章講解了如何通過多個 Path 疊加形成筆鋒效果,還有另外的方式實現筆鋒,并且只需要一條Path就可以了。在講解具體方案之前,我們需要了解一個有意思的工具 PathMeasure ,這是一個非常強大且實用的工具,常用于高級動畫…

從C++開始的編程生活(7)——取地址運算符重載、類型轉換、static成員和友元

前言 本系列文章承接C語言的學習,需要有C語言的基礎才能學會哦~ 第7篇主要講的是有關于C的取地址運算符重載、類型轉換、static成員和友元。 C才起步,都很簡單 目錄 前言 取地址運算符重載 const成員函數 基本語法 特點 取地址運算符重載 類型轉換…

SQL 入門指南:排序與分頁查詢(ORDER BY 多字段排序、LIMIT 分頁實戰)

在 SQL 查詢中,我們常需要 “按報名時間先后看活動名單”“只看第 2 頁的活動報名數據”—— 這些需求靠基礎查詢無法實現,而ORDER BY(排序) 和LIMIT(分頁) 就是解決這類問題的核心工具。今天我們用 “校園…

jodconverter將word轉pdf底層libreoffice的問題

近期項目中使用了word轉pdf的功能&#xff0c;其中借助了遠程服務的jodconverter來處理。 <dependency><groupId>org.jodconverter</groupId><artifactId>jodconverter-remote</artifactId><version>4.4.2</version> </dependen…

【為YOLOv11Seg添加MFC界面】詳細指南

要將現有的YOLOv11Seg代碼集成到MFC界面中,我們需要創建一個MFC應用程序框架,并將現有的檢測邏輯封裝到其中。以下是詳細步驟: 1. 創建MFC應用程序框架 1.1 使用Visual Studio創建MFC項目 打開Visual Studio,選擇"創建新項目" 選擇"MFC應用程序"模板…

機器學習03——線性模型(多元線性回歸、對數線性回歸、二分類、線性判別分析)

上一章&#xff1a;機器學習02——模型評估與選擇 下一章&#xff1a;機器學習04——決策樹 機器學習實戰項目&#xff1a;【從 0 到 1 落地】機器學習實操項目目錄&#xff1a;覆蓋入門到進階&#xff0c;大學生就業 / 競賽必備 文章目錄一、線性模型的基本形式&#xff08;一…

qt QLineSeries詳解

1、概述QLineSeries是Qt Charts模塊中的一個重要類&#xff0c;用于繪制折線圖。它是QXYSeries的實現類&#xff0c;將信息顯示為由直線連接的一系列數據點。該類為QAbstractSeries的子類&#xff0c;因此可以通過該類來訪問QAbstractSeries的所有公共方法和屬性。2、重要方法c…

你再也找不到更詳細的3DGS教程了 —— 一萬九千字長文解析3DGS

參考: https://www.bilibili.com/video/BV1MF4m1V7e3/ https://blog.csdn.net/2401_86810419/article/details/148811121 https://www.bilibili.com/video/BV1cz421872F?t=233.9 https://wuli.wiki/online/SphHar.html https://zhuanlan.zhihu.com/p/467466131 特別指出…

Python,遺傳算法與神經網絡架構搜索:基于DEAP的自動模型設計

引言&#xff1a;當進化論遇見深度學習——自動化的黎明在深度學習的蠻荒時代&#xff0c;我們是“手工匠人”。我們依靠直覺、前輩的經驗&#xff08;ResNet 為什么是152層而不是153層&#xff1f;&#xff09;、大量的試錯以及那么一點點玄學&#xff0c;在架構的黑暗森林中摸…

Vue框架技術詳解——項目驅動概念理解【前端】【Vue】

Vue3框架 是前端渲染框架瀏覽器向服務器第一次發送請求&#xff0c;就會將所有頁面的樣式全部返回到瀏覽器vue中會將所有js文件最后打包成一個js文件&#xff0c;當前訪問其中一個頁面時&#xff0c;其他頁面的樣式也已經返回到瀏覽器中了&#xff0c;下次切換頁面時&#xff…

HTML 網頁靜態托管 API 接口文檔(可集成到智能體Agent)

HTML 網頁靜態托管 API 接口文檔&#xff08;可集成到智能體Agent&#xff09; 接口概述 本接口用于將HTML代碼轉換為可訪問的網頁&#xff0c;支持通過API密鑰進行身份驗證。 API 密鑰申請地址&#xff1a; https://www.cuobiezi.net/user/api_keys/apply API接口信息 接…

springboot vue sse消息推送,封裝系統公共消息推送前后端方法

概述 1、封裝springboot全局的消息推送接口&#xff1b; 注&#xff1a;1&#xff09;由于原生HTML5 EventSource 不支持添加header&#xff0c;所以要把連接創建接口加入身份驗證白名單&#xff0c;并在接口內添加自己校驗token2&#xff09;后臺需定時心跳&#xff0c;保證鏈…

LeetCode 每日一題 2025/9/1-2025/9/7

記錄了初步解題思路 以及本地實現代碼&#xff1b;并不一定為最優 也希望大家能一起探討 一起進步 目錄9/1 1792. 最大平均通過率9/2 3025. 人員站位的方案數 I9/3 3027. 人員站位的方案數 II9/4 3516. 找到最近的人9/5 2749. 得到整數零需要執行的最少操作數9/6 3495. 使數組元…

小迪安全v2023學習筆記(八十講)—— 中間件安全WPS分析WeblogicJenkinsJettyCVE

文章目錄前記服務攻防——第八十天中間件安全&HW2023-WPS分析&Weblogic&Jetty&Jenkins&CVE應用WPS - HW2023-RCE&復現&上線CS介紹漏洞復現中間件 - Weblogic-CVE&反序列化&RCE介紹利用中間件 - Jenkins-CVE&RCE執行介紹漏洞復現CVE-20…

各webshell管理工具流量分析

哥斯拉哥斯拉是一個基于流量、HTTP全加密的webshell管理工具 特點 1.內置了3種Payload以及6種加密器&#xff0c;6種支持腳本后綴&#xff0c;20個內置插件 2.基于java&#xff0c;可以跨平臺使用 3.可以自己生成webshell&#xff0c;根據管理來生成一些payload&#xff0c;然后…

pytest(1):fixture從入門到精通

pytest&#xff08;1&#xff09;&#xff1a;fixture從入門到精通前言1. Fixture 是什么&#xff1f;為什么我們需要它&#xff1f;2. 快速上手&#xff1a;第一個 Fixture 與基本用法3. 作用域 (Scope)&#xff1a;控制 Fixture 的生命周期4. 資源管理&#xff1a;Setup/Tear…

Java17 LTS 新特性用例

基于 Java 17 LTS 的 實用示例 以下是基于 Java 17 LTS 的 30 個實用示例,涵蓋語言新特性、API 改進及常見場景。所有代碼均兼容 Java 17 語法規范。 文本塊(Text Blocks) String json = """{"name": "Java 17","type": &qu…

SpringBoot-Web開發-內容協商——多端內容適配內容協商原理HttpMessageConverter

其它篇章&#xff1a; 一&#xff1a;SpringBoot3-日志——日志原理&日志格式&日志級別&日志分組&文件輸出&文件歸檔&滾動切割 二&#xff1a;SpringBoot3-Web開發-靜態資源——WebMvcAutoConfiguration原理&資源映射&資源緩存&歡迎頁&…

Spring MVC 類型轉換與參數綁定:從架構到實戰

在 Spring MVC 開發中&#xff0c;“前端請求數據” 與 “后端 Java 對象” 的格式差異是高頻痛點 —— 比如前端傳的String類型日期&#xff08;2025-09-08&#xff09;要轉成后端的LocalDate&#xff0c;或者字符串male要轉成GenderEnum.MALE枚舉。Spring 并非通過零散工具解…