简介:基于Vue和Python构建的免费开源接口自动化测试平台设计源码,面向接口测试工程师、前端开发者及测试平台二次开发人员,支持单接口与多场景串联、接口间数据依赖、延迟调用、性能测试、定时任务、模拟接口数据、测试数据与用例分离等完整功能。压缩包共462个文件,大小26.26MB,核心文件包括57个Python后端逻辑文件、39个Vue前端组件、90个JS交互脚本、97个CSS样式文件,以及图片、说明文档、矢量图标等辅助内容;前后端分离架构清晰,目录含后端、前端、部署等模块,并附Docker部署文件便于快速搭建开发与测试环境。已有671人学习下载。项目通过Python处理接口请求发送、响应接收与断言执行,Vue界面简化了配置和报告查看流程;使用文档与目录结构能帮助读者快速上手,开源许可声明清晰,便于按需扩展、定制或集成到现有研发流程。 接口自动化测试这件事,做浅了就是一堆Postman集合,做深了就是一套完整平台。我在不同项目里见过太多种落地方式:有人用Excel维护用例,跑挂了就翻日志;有人在JMeter里写断言,报告全靠截图;还有人直接用Python脚本一把梭,代码和用例完全耦合在一起。这些方案不是不能用,但随着接口数量上来,维护成本高到让人崩溃。
所以我自己动手写了一套免费开源的接口自动化测试平台,前端用Vue 3,后端用Python FastAPI,核心只解决三件事:用例低成本维护、执行结果可视化、团队快速上手。这篇文章会把平台的设计思路、核心源码结构以及二次开发时最容易踩的坑完整讲清楚。无论你是测试开发工程师,还是后端想搭一套内部工具,都可以直接参考,甚至拿源码去改造。
1. 为什么我用了 Vue + Python 这个组合,而不是直接上现成平台
1.1 现成平台的尴尬
很多人提到接口自动化测试,第一反应是去部署一套现成的开源平台。市面上确实有功能完整的方案,但中小团队实际用起来会遇到两个硬伤:一是技术栈偏重,部署一套Java微服务加前端工程再加数据库,光环境准备就能折腾一两天;二是二次开发门槛太高,改一个小功能要翻半天源码,团队根本不敢动。
我自己是从测试转过来的,最清楚这种痛。团队需要的不是功能最全的平台,而是一个接口用例能集中管理、环境能一键切换、报告能自动生成、代码还看得懂的轻量级工具。这个定位听起来简单,但市面上的方案总有一头不满足,要么太重,要么太封闭。
1.2 技术选型背后的理由
后端选Python,原因是写起来快,而且生态里和接口测试关系最密切。requests库做HTTP调用,基本是大半个测试行业的默认选择;断言、数据提取的代码可以写得很简洁;如果后续要做数据驱动、跟CI/CD集成,Python脚本也可以嵌入到流水线的任意环节。
后端框架我选了FastAPI,而不是Flask或Django。原因有三个:自带OpenAPI接口文档,前端联调时直接打开/docs就能看到所有接口定义;原生支持异步,执行并发测试任务时不容易卡死;基于Pydantic做参数校验,前端传过来的用例数据结构不对会自动报错,省掉一大堆手写校验逻辑。
前端选Vue 3加TypeScript。Vue的响应式数据流在编辑测试用例这种表单密集场景下非常顺手;Element Plus把表格、树形控件、弹窗、表单都覆盖了,做后台管理界面效率很高;Vue全家桶(Router、Pinia、Axios)组合的开发门槛相对低,测试和运维的同事要改前端界面也更容易上手。
我常用的选型对比大致是这样:
| 模块 | 我的选型 | 理由 |
|---|---|---|
| 后端框架 | FastAPI | 自带接口文档、异步支持、Pydantic校验 |
| HTTP调用 | requests | 测试行业默认,扩展方便 |
| 前端框架 | Vue 3 + Element Plus | 组件生态成熟,表单场景效率高 |
| 数据库 | SQLite起步,可切换MySQL | 轻量优先,量大了再换 |
| 任务调度 | APScheduler | 比Celery轻,中小项目够用 |
我没有采用微前端或者重型状态管理方案,因为这套平台的复杂度远没到那个程度。很多项目死在过度设计上,平台类工具最重要的就是"简单到大家都愿意用"。
1.3 平台的边界定位
这套平台面向的是中小团队的接口回归测试和冒烟测试场景,重点做"用例集中管理、跑完有报告、失败能定位"这个闭环。它不是压测平台,也不会替代Postman做日常调试——那是另一个维度的事情。把边界明确之后,所有设计都围绕"轻量、可读、可改"三个词展开。后面我会从项目结构、后端核心、前端核心再到部署和二次开发,把整套源码的思路完整讲一下。
2. 项目目录和用例模型:先定约束,再写功能
2.1 前后端目录怎么分
一个开源项目能不能让人看下去,第一印象就是目录结构。我见过太多项目把代码堆在几个模块里,几个月后连作者自己都找不到逻辑。这套平台的后端目录是这样划分的:
backend/ ├── app/ │ ├── main.py # FastAPI入口 │ ├── core/ │ │ ├── config.py # 全局配置(数据库、token密钥、文件存储目录) │ │ └── security.py # 用户认证相关 │ ├── api/ │ │ ├── testcase.py # 用例相关接口 │ │ ├── execute.py # 执行相关接口 │ │ ├── report.py # 报告相关接口 │ │ └── env.py # 环境配置相关接口 │ ├── models/ │ │ └── schemas.py # Pydantic模型定义 │ ├── services/ │ │ ├── executor.py # 测试执行引擎 │ │ ├── assertion.py # 断言服务 │ │ ├── extractor.py # 数据提取服务 │ │ └── report_gen.py # 报告生成服务 │ └── database.py # 数据库连接 ├── requirements.txt └── run.py这样划分之后,每个文件的职责基本能从名字看出来。开发中我特别强调一个原则:路由层不要写业务逻辑,业务逻辑全部放services层。好处是,后面你要加命令行入口或者定时任务入口,直接调用services层就好,不需要走HTTP。
前端同样讲究分层:src/api统一封装后端接口请求,src/views放页面级组件,src/components放可复用组件,src/stores放Pinia状态,src/router管路由。合理拆分组件比写一个超级页面重要得多,这一点在多人协作时尤其明显。
2.2 测试用例数据模型的设计取舍
测试用例是整个平台的核心。一个用例怎么建模,直接决定执行引擎怎么写,也决定前端用例编辑器长什么样。我最终确定的是"一个用例包含多个步骤"的模式,而不是"一个HTTP请求就是一个用例"。
原因是真实接口测试里存在大量依赖关系:先登录拿token,再创建订单,再查询订单。如果把每个请求都独立成用例,token不知道该存在哪里,串联会非常痛苦。所以模型是这样设计的:
# app/models/schemas.py 关键模型 from pydantic import BaseModel from typing import List, Optional, Dict, Any class Step(BaseModel): name: str # 步骤名称 method: str # HTTP方法 url: str # 接口地址 headers: Optional[Dict[str, Any]] = {} # 请求头 params: Optional[Dict[str, Any]] = {} # query参数 body: Optional[Dict[str, Any]] = None # 请求体(支持json/form) extract: Optional[List[Dict]] = [] # 提取字段列表 assertions: Optional[List[Dict]] = [] # 断言列表 sleep: float = 0 # 步骤间延时 class TestCase(BaseModel): name: str description: str = "" env: str = "dev" # 默认使用环境 variables: Optional[Dict[str, Any]] = {} # 用例级变量 steps: List[Step] priority: str = "P1" # 优先级:P0/P1/P2这个模型里几个字段值得说明:extract是列表结构,每个元素表示"从本次响应中提取某个值,命名为某个变量";assertions也是列表结构,每个元素表示一条断言;sleep字段是踩过坑之后加的,有些接口处理是异步的,下单后立刻查询会查不到,加一个可选的延时字段,执行引擎按顺序执行时自动sleep,比在用例里硬编码时间戳规范得多。
前端编辑器和后端执行引擎都是围绕这套模型展开的。模型不复杂,但它是整个系统稳定运行的前提。
2.3 环境配置与变量池设计
接口测试最怕的是"改完测试环境,结果把生产环境也带崩了"。所以平台的环境配置模块单独拎出来,支持配置多套环境:dev、test、staging、prod。每个环境下面维护base_url、账号、密码、公共请求头这些信息,用例里的URL只写相对路径,执行时由引擎把环境的base_url拼上去。
有了这层抽象,一套用例可以在多个环境之间来回跑,只需要在执行时选择环境即可,不用改任何用例内容。执行时还有一个全局变量池的概念:环境配置里的变量和用例里的variables会合并进变量池,每个步骤的提取结果也写入变量池。这个设计让环境差异和用例逻辑彻底解耦——开发环境连开发库,测试环境连测试库,但用例内容一个字都不用改。
3. 后端执行引擎:请求、提取、断言的三步流水线
3.1 执行引擎整体流程
执行引擎是平台里技术含量最高的部分。它的核心逻辑是一条流水线:变量解析、发送请求、提取数据、执行断言、生成报告。具体流程如下:
- 加载用例和当前环境配置,把所有变量合并到变量池。
- 遍历用例的每一步,先做变量替换,把url、body、headers里的
${变量名}替换成变量池中的实际值。 - 用requests发送请求。
- 根据步骤的
extract配置,从响应中提取字段写入变量池。 - 根据步骤的
assertions配置,执行断言,记录通过或失败。 - 处理完所有步骤后,汇总生成报告。
这个流程看着简单,真正做起来有几个细节很容易出错,下面重点说变量替换和数据提取。
3.2 变量替换与数据提取的实现
接口测试里最常用的功能就是上下文传参。比如登录后把token提取出来,后续请求都要带上。我实现了两种提取方式:JSONPath和正则表达式。JSONPath适合JSON响应,用$.data.token这样的语法取嵌套字段,非常直观;正则是兜底方案,响应是文本或者需要从一个HTML页面里取隐藏字段时也能处理。
提取结果统一放入变量池,下一步直接用${变量名}引用。跨请求的数据传递因此变得非常灵活。核心的变量替换逻辑是一个递归函数:
import re from typing import Any, Dict def replace_variables(data: Any, variables: Dict[str, Any]) -> Any: """递归替换 data 中所有字符串里的 ${var} 占位符""" if isinstance(data, str): def repl(match): var_name = match.group(1) value = variables.get(var_name, "") return str(value if value is not None else "") return re.sub(r"\$\{(\w+)\}", repl, data) elif isinstance(data, dict): return {k: replace_variables(v, variables) for k, v in data.items()} elif isinstance(data, list): return [replace_variables(item, variables) for item in data] return data这段递归函数几乎是所有接口自动化平台都离不开的。关键点在于占位符格式必须统一,我定的是${variable},前端编辑时提示更友好,后端正则处理也简单。如果你要自己扩展,注意嵌套结构里也要递归处理,否则body里的变量漏替换是最常见的bug。
3.3 断言机制与并发执行
接口测试里的断言其实就那么几类,不需要设计得太复杂。我实现的基础断言类型如下:
| 断言类型 | 含义 | 示例 |
|---|---|---|
| status_code | HTTP状态码 | 200, 201 |
| json_equal | JSON字段精确匹配 | {"code": 0} |
| json_contains | JSON路径存在 | $.data.token |
| response_time | 响应时间上限 | 1000(毫秒) |
| regex_match | 正则匹配 | 响应体包含指定模式 |
我要特别强调一点:很多人写接口断言只查status_code,但接口返回200不代表业务成功了,异常提示时状态码往往也是200。所以我实际使用中把断言拆成三层:第一层状态码断言,第二层业务成功标识断言(比如JSON中code字段是否等于0),第三层关键业务字段断言(比如列表长度是否大于0、用户ID是否已生成)。三层检查下来,才算完整验证了一个接口。
并发执行方面,我引入了ThreadPoolExecutor做多线程执行,默认并发数控制在5,避免把测试环境打爆。每个请求都设置超时,默认10秒。这两点是线上跑出来的教训:并发太高,目标服务直接拒绝连接,报告全红;不设超时,一个假死接口会拖到整个任务超时,后面所有用例全卡住。
4. 前端核心:Vue 3 + Element Plus 把用例编辑做到顺手
4.1 用例编辑器怎么设计
后端执行引擎的难度在逻辑,前端最难的是用例编辑器。一个用例少则一两个步骤,多则十几个步骤,每个步骤又要填URL、请求头、参数、提取、断言这些信息。如果全部用普通表单堆出来,页面会非常长,填起来体验很差,用户根本不愿意维护。
我的方案是"左侧步骤列表 + 右侧步骤属性编辑"的布局,类似Postman的编辑体验。左侧是一个步骤列表,每个步骤一行,支持拖拽排序、点击切换、右键复制和删除;右侧是选中步骤的属性表单,按请求信息、数据提取、断言、延时四个Tab分组。body参数做了JSON格式和Key-Value格式两种编辑模式,因为有的接口是restful风格的JSON请求体,有的还是传统form表单,两者都得支持。
核心是把StepEditor封装成一个独立组件,根据当前步骤的method类型动态渲染不同的表单字段。这个组件写好了,用例编辑体验就顺了一大半。
4.2 试运行与实时执行反馈
用过Postman的人都知道,写接口时要立刻看响应结果,不然根本不知道请求对不对。所以平台里做了一个"单步试运行"功能:在步骤编辑时点"试运行",前端直接调用后端/api/execute/step接口,后端执行完单个步骤并把响应体、状态码、耗时返回前端,显示在页面下方。
这个功能改起来不复杂,但直接决定平台好不好用。没有它,每次调一个用例都得等整条跑完才能看到结果,排错效率会特别低。
任务级执行时,我用了WebSocket推送执行日志,而不是轮询。前端ExecLogPanel组件监听WebSocket的message事件,每跑完一个步骤就往日志面板追加一行状态。用WebSocket的优势是延迟低、不占多余请求,而且用户能看到"正在执行第3个步骤"这样的实时状态,不会以为跑挂了。
4.3 报告页面的可视化与通知
报告部分用ECharts做了几个基础图表:通过率饼图、失败用例列表、每个步骤的耗时柱状图。报告页面尽量做到一看就懂:顶部是本次执行的总体信息,包括总用例数、通过数、失败数、通过率、耗时;中间是按模块分组的失败用例列表,点开任意失败用例能看到失败步骤和断言信息;底部是响应时间分布图。
后续要接企业微信或钉钉通知,只需要在报告模块加一个webhook配置即可。平台本身不把通知渠道写死,避免依赖具体的通信工具。
5. 快速启动、常见坑和二次开发建议
5.1 本地快速启动
后端启动很简单,创建一个虚拟环境,装依赖,然后跑起来:
cd backend pip install -r requirements.txt python run.py启动后浏览器打开http://127.0.0.1:8000/docs,FastAPI自动生成的接口文档就能直接用,每个接口都能在线调试。
前端启动:
cd frontend npm install npm run dev访问http://127.0.0.1:5173,默认账号admin/admin123登录,就可以开始创建用例了。
5.2 踩过的四个坑
第一个是跨域问题。前端vite运行在5173端口,后端在8000端口,浏览器默认会拦截跨域请求。解决方式是在后端加CORS中间件,允许前端地址访问。如果你自己二次开发,记得修改前端的baseURL配置为后端真实地址。
第二个是Python版本。FastAPI新版本对Python版本要求比较高,建议直接用Python 3.10以上。我在一台老服务器上装过Python 3.7,跑起来一堆兼容问题,后来干脆升级环境才解决。
第三个是Node版本。Vite 4以上需要Node 14.18+,最好直接用Node 16或18。很多"npm install报错"其实都是node版本不对引起的,这个坑比后端多得多。
注意:遇到npm install报错,先检查
node -v是不是满足要求,别一上来就卸载重装依赖。
第四个是数据库初始化。平台默认使用SQLite,零配置即可运行,但部署到正式环境建议改成MySQL,把数据库连接串配置到环境变量里,不要写死在代码里。
5.3 二次开发从哪里入手
如果你是第一次拿到这套源码,建议按这个顺序读:先读backend/app/models/schemas.py理解用例数据模型;再读backend/app/services/executor.py理解执行引擎;然后读frontend/src/views/CaseEdit.vue对应前端编辑界面;最后看stores目录理解状态流转。
二次开发的第一件事,我建议不要急着加功能,而是先跑通一个最简单的用例,用浏览器调试工具看完整请求链路是什么样。把链路摸熟了,后面改任何模块都有底气。
最后再分享一个小技巧:如果你要在团队里推广这套平台,不要一上来就让所有人去配环境。先在服务器上部署一套共享实例,把登录、环境配置、几个典型用例都垫好,让同事打开浏览器就能看到现成的报告。工具这东西,用顺手了才有继续折腾的兴趣。平台本身是开源的,跑起来只是第一步,真正有价值的部分是你们团队沉淀下来的那批用例。
本文还有配套的精品资源,点击获取