跳到正文
博客园· JasonCode编程·· 4 小时前AI 评分22

为什么我放弃 Pytest,从零手搓 AITest 测试执行引擎

为什么我放弃了成熟的 Pytest,选择从零手搓测试执行引擎? - JasonCode编程

AI 导读

独立开发者 Jason 在 AITest 全栈测试平台 100 天复盘中,解释了为何弃用 Pytest 而基于 FastAPI + 异步 Celery 自研执行引擎。

正文

摘要:

前几天发文分享了自研的 AITest 全栈测试平台,今天,借着 100 天复盘,我扒开源码,聊聊为什么在企业级 SaaS 平台里,Pytest 反而是“绊脚石”,以及我们是如何用 FastAPI + 异步 Celery 构建自研执行引擎的。

在推进这个项目的过程中,绕不开的一个问题就是:

“现成的 Pytest、Robot Framework 不香吗?自己写执行引擎,不是纯纯的重复造轮子吗?”

说实话,刚开始我也犹豫过。Pytest 是 Python 测试生态的王者,断言、参数化、插件一应俱全。但当我真正开始设计一套** B/S 架构、支持多租户、带 WebSocket 实时进度、且未来要接入 AI 智能体的测试平台时,我发现:Pytest 的架构基因,与现代化的企业级 Web 测试平台是天生互斥的。**

今天,我们就来硬核拆解一下,为什么我选择放弃 Pytest,从零手搓一套基于“模板方法 + 策略模式”的自研执行引擎。

一、 为什么不用 Pytest?(自研架构的绝对优势)
很多初学者觉得,不用现成的框架就是“不够专业”。但事实恰恰相反,如果你在你的 SaaS 平台底层强塞一个 Pytest,你的平台本质上就变成了一个“套壳的网页版命令行工具”。
而你选择自研引擎,是做企业级测试平台的必然选择,原因有以下四点,招招致命:

1. 多租户与动态配置的灾难
Pytest 是静态的,每次跑测试都需要有具体的 .py 文件。而在 SaaS 平台里,用户是随时随地在网页上修改断言、增减参数的。
如果底层用 Pytest,后端的灾难就来了:每次执行前,你都需要把数据库里成百上千的 JSONB 用例,动态渲染成成百上千个 .py 文件,跑完再删掉。这种高频的 I/O 损耗,以及多租户并发时的文件冲突,在微服务架构下简直是噩梦。而自研引擎,直接从数据库读取最新配置,秒级生效,零文件损耗。

2. 细粒度的进度推送(WebSocket 死局)
用户在网页上点击“执行”,他极度渴望看到实时的进度条(当前跑到第几步了?断言过了没?)。
Pytest 执行时,你很难知道它内部具体跑到哪一步了,只有全部跑完才出结果。而在自研引擎里,可以在每个步骤执行前后,通过 Redis Pub/Sub 发送 WebSocket 消息给前端。你在我的系统截图中看到的那个丝滑的实时进度条,就是自研引擎带来的极致观测体验。

3. 完美的 Celery 异步结合
我的后端是 FastAPI,全链路异步(async/await),执行任务是交给 Celery Worker 的。而 Pytest 是同步阻塞的,强行把它塞进 Celery 的异步环境里,各种 Event loop is closed 的报错会让你怀疑人生。自研引擎天然拥抱 async,完美融入底层架构。

4. 为 V2.0 的 AI 做准备(最核心的降维打击)
到了 2026 年,测试平台的下半场绝对是 AI Agent。如果用 Pytest,大模型根本无法在运行中途插一脚。
但在自研架构下,大模型可以动态决策:“这条断言失败了,我要不要换个参数再试一次?” 大模型可以直接调用自研的 SkillRegistry(技能注册中心),甚至不用发 HTTP 请求,纯做逻辑判断。用 Pytest,框架会把你卡死;用自研引擎,才能拥有极致的扩展性。

二、 那你岂不是重复造轮子了?
很多人会觉得“不用 pytest 是不是显得不够专业”。完全不是!
去看看 Postman、Apifox 等所有现代测试平台,底层全都是自己写的执行引擎,没有一个是直接用 pytest 的。 为什么?因为它们要支持可视化的拖拽、实时进度、参数化渲染、环境变量隔离,这些用现成的测试框架根本搞不定。
Pytest 的优势在于单机上的单元测试,但它的缺点是重度依赖本地 Python 文件。我们要做的是 Web 化的 SaaS 平台,所以底层的 Executor(执行器) 和 Skill(技能) 都是纯硬编码的异步引擎。这样做的好处是:

  1. 完美支持 WebSocket 实时进度推送。
  2. 支持用户在前端页面上随时改配置,秒级生效,不需要动态生成 Python 文件。
  3. 最关键的是,为了近期上 AI 功能。未来 AI 智能体(Agent)要动态调用这些执行技能,如果用 pytest 会被框架卡死,自研引擎才能拥有极致的扩展性。

三、 揭秘自研引擎的架构底牌(硬核源码曝光)
既然不用 Pytest,我是怎么处理 HTTP 请求、提取变量、执行断言的?
我的底层架构完全遵循了“分层设计”和“设计模式”,将其拆分为两个核心角色:执行器(Executor) 和 技能(Skill)。

1. 模板方法模式:统一执行骨架(Executor)
所有的测试用例,无论是单接口用例还是多步骤场景,执行流程都是固定的:加载数据 -> 循环步骤 -> 执行请求 -> 断言结果 -> 写入数据库。
我定义了一个 BaseExecutor 基类(模板方法),把公共骨架写死,子类只需要实现具体的步骤逻辑:

# 核心代码片段:基于模板方法的执行器
from abc import ABC, abstractmethod

class BaseExecutor(ABC):
    """执行器抽象基类(模板方法模式)"""

    async def execute(self):
        # 1. 前置校验与加载
        await self._load_data()

        # 2. 遍历步骤(具体实现由子类定义)
        for step in self.steps:
            result = await self._execute_step(step)
            # 3. 实时推送进度到前端 WS
            await self._push_progress(result)

        # 4. 汇总落库
        await self._persist_result()

    @abstractmethod
    async def _execute_step(self, step):
        """子类必须实现的具体执行逻辑"""
        pass

class SerialExecutor(BaseExecutor):
    """单用例串行执行器"""
    async def _execute_step(self, step):
        # 调用底层的 Skill 执行单步
        return await skill_registry.execute("http_request", step)

2. 策略模式:能力原子化(Skill Registry)
这是整个系统最精妙的地方。我不把“发 HTTP 请求”或“提取变量”写死在 Executor 里,而是把它们抽象成一个个可插拔的“技能(Skill)”。
不仅传统模式可以用,未来 V2.0 的大模型(Agent)也可以通过 MCP 协议直接调用这些技能!

# 核心代码片段:基于策略模式的技能注册中心
class BaseSkill(ABC):
    @abstractmethod
    async def execute(self, params: dict) -> dict:
        pass

class AssertSkill(BaseSkill):
    """断言技能:纯硬编码实现各种断言逻辑"""
    async def execute(self, params: dict) -> dict:
        actual = extract_json_path(params["actual_response"], params["path"])
        expected = params["expected"]
        op = params["operator"]

        # 硬编码断言引擎,极速且稳定
        is_pass = False
        if op == "equals":
            is_pass = (actual == expected)
        elif op == "contains":
            is_pass = (expected in actual)

        return {"status": is_pass, "actual": actual}

单例注册中心:启动时将所有技能注册进去

skill_registry.register("assert_result", AssertSkill())

通过这种设计,用户在前端拖拽配一个断言,后端直接转化为参数 {path: "data.token", operator: "not_null"},传给 AssertSkill 执行。没有繁重的框架负担,只有极致的执行效率。

四、 100 天的心血,全部开源分享
从数据库设计(36 张表)、后端架构(FastAPI + 三层 RBAC + Celery),到前端(Vue3 + 极致的 UnoCSS 规范),这 100 天我踩平了无数个坑。

现在,AITest V1.0 版本已正式发布!

平台登录页:
平台登录页

个人工作台:
个人工作台

为了帮助更多在测试开发、全栈开发路上迷茫的同学,我把这套系统的 《架构设计文档 (SAD)》、《前后端开发规范》以及第一阶段的完整基础骨架源码 整理出来了。

你可以直接拿去:
● 作为简历里的硬核全栈项目(秒杀千篇一律的商城 Demo)。
● 学习 FastAPI 异步生态、Vue3 工程化的最佳实践。
● 为接下来的 AI 智能体开发打好底层基础。

👉 获取方式:
关注公众号 【JasonCode编程】(如果你想和我一起交流架构、探讨 AI 测试的未来,也欢迎在后台加我微信,拉你进内部技术群!),后台回复 【星球】,即可获取全套架构文档 + 源码资料包。
(如果你想和我一起交流架构、探讨 AI 测试的未来,也欢迎在后台加我微信,拉你进内部技术群!)
我是 Jason,独立开发者。V2.0 的 AI 智能体开发日记即将开启,关注我,带你手搓下一代 AI 测试平台。

来源:博客园 · cnblogs.com