用 PyQt5 和 asyncio 打造接口并发测试 GUI 工具
接口并发测试是测试工程师日常工作中的重要一环,而一个直观的 GUI 工具能有效提升工作效率和体验。本篇文章将带你用 PyQt5 和 asyncio 从零实现一个美观且功能实用的接口并发测试工具。
我们将实现以下功能:
-
请求方法选择器
添加了一个下拉框QComboBox,用户可以选择GET、POST、PUT、DELETE或PATCH。 -
动态请求方法
根据用户选择的请求方法,在send_request函数中动态调用对应的aiohttp方法(如session.get或session.post)。 -
异常处理
如果用户选择了不支持的请求方法,会返回"Unsupported Method"错误。
使用方法
- 在界面上输入请求的 URL。
- 选择所需的 请求方法(如
GET、POST等)。 - 输入 请求头 和 请求参数(JSON 格式)。
- 设置 并发请求次数,点击“开始测试”。
- 查看结果表格中每个请求的序号、状态码和响应时间。
下面是完整的代码实现以及详细的注释,帮助你快速上手。

代码实现
1. 安装依赖
在开始之前,请确保安装了必要的依赖库:
pip install pyqt5 aiohttp
2. 主代码
以下是完整的代码实现:
import sys
import asyncio
import aiohttp
from PyQt5.QtWidgets import (QApplication, QWidget, QLabel, QLineEdit, QTextEdit, QVBoxLayout, QHBoxLayout, QPushButton, QSpinBox, QTableWidget, QTableWidgetItem
)
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QFontclass AsyncHttpTester(QWidget):def __init__(self):super().__init__()self.init_ui()def init_ui(self):"""初始化用户界面"""self.setWindowTitle("接口并发测试工具")self.setGeometry(100, 100, 800, 600)self.setFont(QFont("Arial", 10))# === 接口配置区 ===url_label = QLabel("请求 URL:")self.url_input = QLineEdit()self.url_input.setPlaceholderText("请输入接口 URL")headers_label = QLabel("请求头 (JSON 格式):")self.headers_input = QTextEdit()self.headers_input.setPlaceholderText('例如:{"Content-Type": "application/json"}')params_label = QLabel("请求参数 (JSON 格式):")self.params_input = QTextEdit()self.params_input.setPlaceholderText('例如:{"key": "value"}')times_label = QLabel("发送次数:")self.times_input = QSpinBox()self.times_input.setRange(1, 1000)self.times_input.setValue(1)# === 开始按钮 ===self.start_button = QPushButton("开始测试")self.start_button.clicked.connect(self.start_test)# === 结果展示区 ===results_label = QLabel("测试结果:")self.results_table = QTableWidget()self.results_table.setColumnCount(3)self.results_table.setHorizontalHeaderLabels(["请求序号", "状态码", "响应时间 (秒)"])self.results_table.setColumnWidth(0, 100)self.results_table.setColumnWidth(1, 100)self.results_table.setColumnWidth(2, 150)# === 布局 ===layout = QVBoxLayout()# 接口配置布局config_layout = QVBoxLayout()config_layout.addWidget(url_label)config_layout.addWidget(self.url_input)config_layout.addWidget(headers_label)config_layout.addWidget(self.headers_input)config_layout.addWidget(params_label)config_layout.addWidget(self.params_input)config_layout.addWidget(times_label)config_layout.addWidget(self.times_input)# 添加开始按钮config_layout.addWidget(self.start_button)# 结果展示布局results_layout = QVBoxLayout()results_layout.addWidget(results_label)results_layout.addWidget(self.results_table)# 整合布局layout.addLayout(config_layout)layout.addLayout(results_layout)self.setLayout(layout)async def send_request(self, session, url, headers, params, index):"""发送单个 HTTP 请求"""try:async with session.post(url, json=params, headers=headers) as response:elapsed = response.elapsed.total_seconds() if response.elapsed else 0return index, response.status, elapsedexcept Exception as e:return index, f"Error: {str(e)}", 0async def start_async_requests(self, url, headers, params, times):"""启动并发请求"""tasks = []async with aiohttp.ClientSession() as session:for i in range(times):tasks.append(self.send_request(session, url, headers, params, i + 1))return await asyncio.gather(*tasks)def start_test(self):"""开始测试按钮事件"""url = self.url_input.text().strip()try:headers = eval(self.headers_input.toPlainText().strip()) if self.headers_input.toPlainText().strip() else {}params = eval(self.params_input.toPlainText().strip()) if self.params_input.toPlainText().strip() else {}except Exception as e:self.results_table.setRowCount(0)self.results_table.setRowCount(1)self.results_table.setItem(0, 0, QTableWidgetItem("Error"))self.results_table.setItem(0, 1, QTableWidgetItem(f"Invalid headers/params: {str(e)}"))returntimes = self.times_input.value()if not url:self.results_table.setRowCount(0)self.results_table.setRowCount(1)self.results_table.setItem(0, 0, QTableWidgetItem("Error"))self.results_table.setItem(0, 1, QTableWidgetItem("URL 不能为空"))return# 清空结果表self.results_table.setRowCount(0)# 启动异步任务loop = asyncio.get_event_loop()results = loop.run_until_complete(self.start_async_requests(url, headers, params, times))# 更新结果表self.results_table.setRowCount(len(results))for i, (index, status, elapsed) in enumerate(results):self.results_table.setItem(i, 0, QTableWidgetItem(str(index)))self.results_table.setItem(i, 1, QTableWidgetItem(str(status)))self.results_table.setItem(i, 2, QTableWidgetItem(f"{elapsed:.2f}"))if __name__ == "__main__":app = QApplication(sys.argv)tester = AsyncHttpTester()tester.show()sys.exit(app.exec_())
功能解析
1. 界面设计
- 使用 PyQt5 构建界面,布局由
QVBoxLayout和QHBoxLayout组合,模块化分为“配置区”和“结果区”。 - 支持输入 URL、请求头、请求参数、以及指定发送次数。
2. 异步请求
- 使用
aiohttp.ClientSession实现非阻塞的 HTTP 请求。 - 通过
asyncio.gather并发发送多个请求,收集结果。
3. 响应展示
- 结果以表格形式展示,包含请求序号、状态码、响应时间,方便对比和分析。
运行效果
- 启动工具后,用户可以在界面上输入接口参数,例如 URL、请求头、请求体等。
- 点击“开始测试”后,工具会并发发送指定次数的请求,并实时展示结果。
总结
通过 PyQt5 和 asyncio,我们成功实现了一个美观实用的接口并发测试工具。在这个项目中,测试工程师可以直观地配置接口参数并分析响应结果,同时也能深入理解 Python 的异步编程原理。
赶紧试试吧!
相关文章:
用 PyQt5 和 asyncio 打造接口并发测试 GUI 工具
接口并发测试是测试工程师日常工作中的重要一环,而一个直观的 GUI 工具能有效提升工作效率和体验。本篇文章将带你用 PyQt5 和 asyncio 从零实现一个美观且功能实用的接口并发测试工具。 我们将实现以下功能: 请求方法选择器 添加了一个下拉框 QComboBo…...
OpenHarmony Camera开发指导(四):相机会话管理(ArkTS)
概述 相机在使用预览、拍照、录像、获取元数据等功能前,都需要先创建相机会话。 相机会话Session的功能如下: 配置相机的输入流和输出流。 配置输入流即添加设备输入,通俗来讲即选择某一个摄像头进行拍照录像;配置输出流&#x…...
深入探索RAG(检索增强生成)模型的优化技巧
📌 友情提示: 本文内容由银河易创AI(https://ai.eaigx.com)创作平台的gpt-4o-mini模型生成,旨在提供技术参考与灵感启发。文中观点或代码示例需结合实际情况验证,建议读者通过官方文档或实践进一步确认其准…...
Spring boot 中的IOC容器对Bean的管理
Spring Boot 中 IOC 容器对 Bean 的管理,涵盖从容器启动到 Bean 的生命周期管理的全流程。 步骤 1:理解 Spring Boot 的容器启动 Spring Boot 的 IOC 容器基于 ApplicationContext,在应用启动时自动初始化。 入口类:通过 SpringB…...
Qt实战之将自定义插件(minGW)显示到Qt Creator列表的方法
Qt以其强大的跨平台特性和丰富的功能,成为众多开发者构建图形用户界面(GUI)应用程序的首选框架。而在Qt开发的过程中,自定义插件能够极大地拓展应用程序的功能边界,让开发者实现各种独特的、个性化的交互效果。想象一下…...
【Vue】TypeScript与Vue3集成
个人主页:Guiat 归属专栏:Vue 文章目录 1. 前言2. 环境准备与基础搭建2.1. 安装 Node.js 与 npm/yarn/pnpm2.2. 创建 Vue3 TypeScript 项目2.2.1. 使用 Vue CLI2.2.2. 使用 Vite(推荐)2.2.3. 目录结构简述 3. Vue3 TS 基础语法整…...
Linux之七大难命令(The Seven Difficult Commands of Linux)
Linux之七大难命令 、背景 作为Linux的初学者,肯定要先掌握高频使用的指令,这样才能让Linux的学习在短时间内事半功倍。但是,有些指令虽然功能强大,但因参数多而让初学者们很害怕,今天介绍Linux中高频使用࿰…...
Spring Boot单元测试实战指南:从零到高效测试
在Spring Boot开发中,单元测试是保障代码质量的核心环节。本文将基于实际开发场景,手把手教你如何快速实现分层测试、模拟依赖、编写高效断言,并分享最佳实践! 一、5分钟环境搭建 添加依赖 在pom.xml中引入spring-boot-starter-te…...
5.3.1 MvvmLight以及CommunityToolkit.Mvvm介绍
MvvmLight、CommunityToolkit.Mvvm是开源包,他们为实现 MVVM(Model-View-ViewModel)模式提供了一系列实用的特性和工具,能帮助开发者更高效地构建 WPF、UWP、MAUI 等应用程序。 本文介绍如下: 一、使用(旧)的MvvmLight库 其特点如下,要继承的基类是ViewModelBase;且使用…...
Dbeaver 执行 SQL 语句和执行 SQL 脚本的区别
执行 SQL 语句 执行 SQL 语句对应图标: 适用于执行单个 SQL 的情形,默认是在光标处或选中的文本上执行 SQL 查询。 实际上同时选择多个 SQL 并通过该方式去执行也可能成功,只是有失败的风险。因此不建议使用它来同时执行多个 SQL 语句。 情况…...
《Python3网络爬虫开发实战(第二版)》配套案例 spa6
Scrape | Moviehttps://spa6.scrape.center/ 请求影片列表api时,不仅有分页参数,还多了一个token,通过重发请求发现token有时间限制,所以得逆向token的生成代码。 通过xhr断点定位到接口请求位置 刷新页面或者点翻页按钮&#x…...
AWS 中国区 CloudFront SSL 证书到期更换实战指南
适用场景: AWS 中国区(宁夏区域 cn-northwest-1 或北京区域 cn-north-1)CloudFront 分配的 SSL 证书到期后无缝替换,域名主体为 domain.cn。 背景与痛点 当 CloudFront 使用的 SSL 证书即将到期时,需手动替换新证书以避免服务中断。由于 AWS 中国区 不支持 ACM 证书,必须…...
Python基础语法:字面量,注释,关键字,标识符,变量和引用,程序执行的3大流程
目录 字面量(数据的类型) 字面量的含义 常见字面量类型(6种) 输出各类字面量(print语句) 注释(单行和多行注释) 注释的作用 单行注释和多行注释 单行注释(ctrl/&a…...
SPL 量化 获取数据
下载数据 我们将股票数据分享在百度网盘上供下载,每工作日更新。 目前可供下载的数据有 A 股的日 K 线数据、股票代码列表和上市公司的基本面数据 下载链接: 百度网盘 下载数据的文件格式为 btx,是 SPL 的特有二进制格式。 btx 称为集文…...
VMware与Docker:虚拟化技术的双轨演进与融合实践
一、虚拟化的本质与价值重构 虚拟化(Virtualization)是通过软件抽象层将物理资源转化为可动态分配的虚拟单元,其核心价值在于打破"一机一用"的刚性架构,实现三大突破性转变: 资源解耦:硬件资源…...
3. pandas笔记之:创建
以下是 Pandas 主要数据结构的创建方式整理,涵盖 Series 和 DataFrame 的常见创建方法: 一、Series 创建方式 从列表/数组创建 import pandas as pd import numpy as np# 基础列表 s1 pd.Series([1, 3, 5, np.nan, 6])# 指定索引 s2 pd.Series([10, …...
潞晨科技将暂停DeepSeek API服务,AI大模型技术红利普惠化与市场竞争白热化叠加,内卷恶果,开始显现!
潞晨科技宣布暂停DeepSeek API服务的事件,不仅暴露了AI大模型行业的技术与成本博弈,更折射出国内AI生态中中小企业的生存困境和行业内卷的深层矛盾。这一事件背后,既有企业个体商业模式的局限性,也揭示了整个行业在技术迭代、成本控制和市场策略上的系统性挑战。 一、潞晨科…...
某大型电解铝厂电解系统谐波治理装置改造沃伦森电气
电解铝行业谐波治理解决方案——无源滤波装置优化升级,保障稳定运行 在电解铝生产过程中,谐波污染问题严重影响电网电能质量,甚至可能导致滤波装置损坏,引发群爆事故。河南登封某大型电解铝厂通过无源滤波装置智能化改造ÿ…...
Rust 学习笔记:安装 Rust
Rust 学习笔记:安装 Rust Rust 学习笔记:安装 Rust在 Windows 上安装 Rust命令行创建 Rust 项目在 Mac/Linux 上安装 Rust一些命令升级卸载cargo -hrustc -h 安装 RustRoverrust-analyzer Rust 学习笔记:安装 Rust 在 Windows 上安装 Rust …...
精准落地设计,现代项目管理中的深度实践
在数字化转型浪潮席卷全球的当下,项目管理的复杂性呈指数级增长。无论是软件开发、大型工程建设,还是企业流程再造,都面临着设计理念与实际执行之间的鸿沟。《人月神话》第6章中关于确保体系结构师设计准确落地的论述,为破解这一难…...
编译 C++ 报错“找不到 g++ 编译器”的终极解决方案(含 Windows/Linux/macOS)
前言 在使用终端编译 C 程序时,报错: 或类似提示,意味着你的系统尚未正确安装或配置 g 编译器。本篇将从零手把手教你在 Windows / Linux / macOS 下安装并配置 g,适用于新手或 C 入门阶段的你。 什么是 g? g 是 GN…...
联易融出席深圳链主企业供应链金融座谈会,加速对接票交所系统
近日,深圳市委金融办组织召开全市链主企业供应链金融高质量发展座谈会。联易融作为供应链金融企业代表,与虾皮信息科技、电子元器件和集成电路国际交易中心等代表性机构以及行业协会、金融机构参加了会议。 发展供应链金融是破解中小微企业融资难、融资…...
html单页业务介绍源码
源码介绍 html单页业务介绍源码,源码由HTMLCSSJS组成,记事本打开源码文件可以进行内容文字之类的修改,双击html文件可以本地运行 效果预览 源码免费获取 html单页业务介绍源码...
单体OJ项目
单体项目版本、微服务版还需我再钻研钻研。 项目介绍 在系统前台,管理员可以创建、管理题目;用户可以自由搜索题目、阅读题目、编写并提交代码。 在系统后端,能够根据管理员设定的题目测试用例在代码沙箱 中对代码进行编译、运行、判断输出是否正确。 其…...
豆包桌面版 1.47.4 可做浏览器,免安装绿色版
自己动手升级更新办法: 下载新版本后安装,把 C:\Users\用户名\AppData\Local\Doubao\Application 文件夹的文件,拷贝替换 DoubaoPortable\App\Doubao 文件夹的文件,就升级成功了。 再把安装的豆包彻底卸载就可以。 桌面版比网页版…...
数据分析案例:医疗健康数据分析
目录 数据分析案例:医疗健康数据分析1. 项目背景2. 数据加载与预处理2.1 加载数据2.2 数据清洗3. 探索性数据分析(EDA)3.1 再入院率概览3.2 按年龄分组的再入院率3.3 住院时长与再入院4. 特征工程与可视化5. 模型构建与评估5.1 数据划分5.2 训练逻辑回归5.3 模型评估6. 业务…...
【MySQL】索引失效问题详解
目录 1. 最左前缀原则 2. 条件左边有函数或运算 3. 隐式类型转换 4. LIKE 模糊查询以 % 开头 5、MySQL 优化器选择全表扫描 ⭐对 in 关键字特别说明⭐ (1)列表太大时,走全表扫描了 (2)隐式类型转换 ÿ…...
Qt实现语言切换的完整方案
在Qt中实现语言动态切换需要以下几个关键步骤,我将提供一个完整的实现方案: 一、准备工作 在代码中使用tr()标记所有需要翻译的字符串 cpp button->setText(tr("Submit")); 创建翻译文件 在.pro文件中添加: qmake TRANSLATION…...
MongoDB(docker版)备份还原
docker启动MongoDB docker run -d -p 27017:27017 --name my-mongo -v /mongodb/db:/data/db mongo备份MongoDB 使用mongodump备份数据库时,默认会将备份数据保存在当前工作目录下的dump文件夹中。 docker容器中默认备份在当前工作目录,所以此处指定当…...
优选算法第十讲:字符串
优选算法第十讲:字符串 1.最长公共前缀2.最长回文子串3.二进制求和4.字符串相乘 1.最长公共前缀 2.最长回文子串 3.二进制求和 4.字符串相乘...
