用 PyQt5 和 asyncio 打造接口并发测试 GUI 工具

接口并发测试是测试工程师日常工作中的重要一环,而一个直观的 GUI 工具能有效提升工作效率和体验。本篇文章将带你用 PyQt5 和 asyncio 从零实现一个美观且功能实用的接口并发测试工具。

我们将实现以下功能:

  1. 请求方法选择器
    添加了一个下拉框 QComboBox,用户可以选择 GETPOSTPUTDELETEPATCH

  2. 动态请求方法
    根据用户选择的请求方法,在 send_request 函数中动态调用对应的 aiohttp 方法(如 session.getsession.post)。

  3. 异常处理
    如果用户选择了不支持的请求方法,会返回 "Unsupported Method" 错误。


使用方法

  1. 在界面上输入请求的 URL
  2. 选择所需的 请求方法(如 GETPOST 等)。
  3. 输入 请求头请求参数(JSON 格式)。
  4. 设置 并发请求次数,点击“开始测试”。
  5. 查看结果表格中每个请求的序号、状态码和响应时间。

下面是完整的代码实现以及详细的注释,帮助你快速上手。
在这里插入图片描述


代码实现

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 构建界面,布局由 QVBoxLayoutQHBoxLayout 组合,模块化分为“配置区”和“结果区”。
  • 支持输入 URL、请求头、请求参数、以及指定发送次数。

2. 异步请求

  • 使用 aiohttp.ClientSession 实现非阻塞的 HTTP 请求。
  • 通过 asyncio.gather 并发发送多个请求,收集结果。

3. 响应展示

  • 结果以表格形式展示,包含请求序号、状态码、响应时间,方便对比和分析。

运行效果

  1. 启动工具后,用户可以在界面上输入接口参数,例如 URL、请求头、请求体等。
  2. 点击“开始测试”后,工具会并发发送指定次数的请求,并实时展示结果。

总结

通过 PyQt5 和 asyncio,我们成功实现了一个美观实用的接口并发测试工具。在这个项目中,测试工程师可以直观地配置接口参数并分析响应结果,同时也能深入理解 Python 的异步编程原理。

赶紧试试吧!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/902722.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

理解npm的工作原理:优化你的项目依赖管理流程

目录 什么是npm npm核心功能 npm 常用指令及其作用 执行npm i 发生了什么? 1. 解析命令与参数 2. 检查依赖文件 3. 依赖版本解析与树构建 4. 缓存检查与包下载 5. 解压包到 node_modules 6. 更新 package-lock.json 7. 处理特殊依赖类型 8. 执行生命周期脚本 9. …

React Native 安卓端 android Image 播放gif webp 动态图

React Native 安卓端 android Image 播放gif webp 动态图 RN项目是0.78.2 React是19.0 基本介绍 Image 是 React Native 中用于显示各种类型图片的核心组件,支持显示网络图片、静态资源、本地图片以及 base64 编码的图片。在 Android 端,Image 组件还可…

实时数字人——DH_LIVE

前两天亲手搭建了实时对话数字人VideoChat,今天来搭建下DH_LIVE。 DH_LIVE一个实时数字人解决方案,从输入文字到数字人对口型说话用时2-3秒。 今天就来实际操作下dh_live的搭建过程。 首先贴上git地址:https://github.com/kleinlee/DH_liv…

AOSP CachedAppOptimizer 冻结方案

背景 Android 一直面临一个核心难题:如何优化进程对有限系统资源(如 CPU、电量)的使用,同时保证用户体验。 当进程进入后台后,它们虽不再贡献用户体验,却仍可能消耗资源。传统的杀后台方案虽然节省资源&a…

实体店的小程序转型之路:拥抱新零售的密码-中小企实战运营和营销工作室博客

实体店的小程序转型之路:拥抱新零售的密码-中小企实战运营和营销工作室博客 在当今数字化浪潮的冲击下,实体店面临着前所未有的挑战,但小程序的出现为实体店转型新零售带来了新的曙光。先来看一组惊人的数据,据相关统计&#xff…

Java求职面试:从Spring Boot到微服务的全面考核

Java求职面试实录:从Spring Boot到微服务的全面考核 第一轮:基础技术的考察 场景: 赵大宝走进了一家互联网大厂的面试间,面试官严肃地看着他。 面试官: 赵大宝,你好。我们先从简单的开始。请你解释一下J…

记录一个坑关于STM32 ARM Compiler Version

在用 Keil 进行 STM32 开发的时候,一开始下载,下载的 ARM 编译器是 Version6,他就不兼容老的代码,就很抽象。 所以必须要更换编译器。 可以去官网下载编译器 Downloads - Arm Developer ,也可以自己找资源哈&#xff…

PCIe体系结构学习入门——PCI总线概述(二)PCI总线的桥和配置

这里写目录标题 序言存储器域和 PCI 总线域HOST 主桥PCI 桥和 PCI 设备配置空间PCI 桥PCI 设备配置空间PCI 总线的配置非透明 PCI 桥序言 接续前章内容,本章继续讲述 PCI 总线概述的第二部分——PCI 总线的桥和配置。 如果需要进一步了解前一章节内容,可以访问:PCIe体系结构…

浔川代码编辑器v2.0(测试版)更新公告

浔川代码编辑器v2.0(测试版)更新公告 发布日期:** 2023年4月30日 我们很高兴地宣布浔川代码编辑器v2.0测试版即将上线!本次更新带来了多项功能改进和问题修复,旨在为用户提供更稳定、更强大的编程体验。 主要更新内容 1. **Bug修复与稳定性提…

微信小程序 tabbar底部导航栏

官方文档:https://developers.weixin.qq.com/miniprogram/dev/reference/configuration/app.html#tabBar 一、常规菜单格式 在app.json 文件中配置,其他关键点详见官方文档,后续更新不规则图标的写法

Spring 中@Autowired,@Resource,@Inject 注解实现原理

使用案例 前置条件: 现在有一个 Vehicle 接口,它有两个实现类 Bus 和 Car ,现在还有一个类 VehicleService 需要注入一个 Vehicle 类型的 Bean: public interface Vehicle {}Component public class Car implements Vehicle {}C…

【Rust结构体】Rust结构体详解:从基础到高级应用

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,…

《LightLLM:开启大语言模型推理新时代》

《LightLLM:开启大语言模型推理新时代》 大语言模型推理的困境与挑战 在当今人工智能飞速发展的时代,大语言模型(LLMs)无疑是最为耀眼的明星技术之一。从 OpenAI 的 GPT 系列到谷歌的 BERT,再到国内如百度文心一言、阿里通义千问等,大语言模型以其强大的语言理解和生成能…

【Python Web开发】02-Socket网络编程02

文章目录 1. 服务器端1.1 socket.socket()1.2 socket.bind()1.3 socket.listen()1.4 socket.accept()1.5 socket.recv()1.6 socket.send() 和 socket.sendall()1.7 socket.close() 2. 客户端2.1 socket.socket()2.2 socket.connect()2.3 socket.send() 和 socket.sendall()2.4 …

Flutter 在全新 Platform 和 UI 线程合并后,出现了什么大坑和变化?

Flutter 在全新 Platform 和 UI 线程合并后,出现了什么大坑和变化? 在两个月前,我们就聊过 3.29 上《Platform 和 UI 线程合并》的具体原因和实现方式,而事实上 Platform 和 UI 线程合并,确实为后续原生语言和 Dart 的…

蓝桥杯 1. 四平方和

四平方和 原题目链接 题目描述 四平方和定理(又称拉格朗日定理)指出: 每个正整数都可以表示为 至多 4 个正整数的平方和。 如果将 0 包括进去,则每个正整数都可以恰好表示为 4 个非负整数的平方和。 例如: 5 0 …

开发并发布一个属于自己的包(npm)

一、CommonJS规范导入require 创建一个npm包涉及几个步骤,包括设置你的项目结构、编写代码、编写文档、测试你的代码,以及发布到npm仓库。以下是一个基本的指南,帮助你从头开始创建一个npm包。 步骤 1: 初始化npm项目 创建项目文件夹&#x…

CRTP(Curiously Recurring Template Pattern)

C 中的 CRTP(奇异递归模板模式) CRTP(Curiously Recurring Template Pattern)是一种利用模板继承实现 静态多态(Static Polymorphism) 的设计模式。通过基类模板以派生类作为模板参数,CRTP 允许…

小白工具视频转MPG, 功能丰富齐全,无需下载软件,在线使用,超实用

在视频格式转换需求日益多样的今天,小白工具网的在线视频转 MPG 功能https://www.xiaobaitool.net/videos/convert-to-mpg/ )脱颖而出,凭借其出色特性,成为众多用户处理视频格式转换的优质选择。 从格式兼容性来看,它支…

银河麒麟系统离线安装nodejs

本篇文章我们介绍如何通过nvm(node版本管理工具)来实现离线安装nodejs 第一步:下载nvm https://github.com/nvm-sh/nvm/releases/tag/v0.40.1 在页面找到【Source code(tar.gz)】下载 第二步:安装nvm 将下载好的tar.gz拷贝到银河麒麟系统文件夹下(加…