做接口自动化测试这些年,被问得最多的一个问题就是:框架到底怎么搭。很多人一开始是看网上教程,今天学着用这个工具,明天又换那个库,折腾一两个月,最后留下的东西自己都懒得维护。以我实际踩过来的经验,接口自动化测试框架搭建这件事,真正的难点从来不是某个工具不会用,而是整体思路不清晰、边界没划明白。这篇就把我从零到一搭框架的完整经验整理一遍,希望能让正在搭框架的你少走几个弯路。
这套框架能做到什么程度呢?简单说就是:测试数据和脚本分离、接口依赖自动处理、执行结果自动生成报告并能被流水线识别、用例可以稳定地跑在每天凌晨的定时任务里。适合正在从手工测试转向自动化测试的工程师,也适合想独立搭建一套接口自动化测试体系、但还在纠结怎么开工的测试开发同学参考。基于经验和通用实践整理,内容偏落地,不是概念堆砌。
1. 接口自动化测试框架搭建的整体设计思路
1.1 先搞清楚框架到底要解决什么问题
每次有人让我帮忙看框架方案,我都会先反问一句:你要解决的核心问题是什么?不少人对这个问题的回答很模糊,只说是"为了让接口测试自动化"。这个答案等于没答。框架如果不知道自己为谁服务、解决什么痛点,搭出来大概率是自娱自乐。
以我个人的理解,接口自动化测试框架要解决的事情可以压缩成三件:第一,用例能快速编写,新接口进来之后,测试人员不用从零写一堆样板代码;第二,回归能稳定执行,一套用例放在那里,今天跑和下周跑结果是一致的,不会因为环境、数据、顺序问题频繁误报;第三,结果能推动研发解决问题,失败信息要直观到让研发一眼看出是哪个接口、哪个字段、预期是什么、实际是什么。
把这三个问题作为设计目标,后面所有的技术选型和功能取舍都有了判断标准。凡是跟这三个目标关系不大的功能,第一批版本都不应该做。比如有的框架一上来就做复杂的多环境自动部署,有的非要接消息队列做异步断言,这些在一个回归框架里优先级其实很低。框架是给业务服务的,不是业务给框架服务的,这个主次一定要分清楚。
1.2 技术选型:为什么我推荐Python加pytest
技术选型是框架搭建中最容易被纠结的环节,也是一旦选错后面很难回头的决策。Java系有TestNG加RestAssured的老牌组合,Python系有pytest加requests的主流方案,这几年又有HttpRunner、Robot Framework这类偏平台化的工具。我的实际体会是:如果团队没有历史包袱,Python加pytest是最省心也最持久的组合。
选它的理由主要有三个。第一,Python语法的学习门槛低,团队里做功能测试的同事翻一翻文档就能看懂用例,这决定了框架能不能在团队里推广开,再厉害的框架没人用就是零。第二,pytest的生态非常成熟,pytest-html做测试报告、pytest-xdist做并发执行、pytest-assume做软断言、pytest-ordering控制执行顺序,工程化需要的能力几乎都有现成的插件,不需要自己造轮子。第三,requests库配合jsonpath、jsonschema这些库,无论是发请求、动态提取字段还是做复杂结构校验,写起来都干净利落,维护成本低。
当然也有例外,如果你的团队本身就是Java技术栈为主,接口自动化的脚本需要跟Java服务共享加密、签名这类工具类代码,那用RestAssured加TestNG同样能搭出不错的框架。选型的核心原则是选团队里大多数人能驾驭的,而不是选你个人觉得最酷的。我见过不少技术方案因为选了一个冷门框架,最后团队成员学不会,整个项目黄掉的例子。
1.3 框架分层架构设计
框架搭到后面好不好维护,很大程度上取决于一开始的分层是否清晰。我一直用的是四层结构:工具层、核心层、业务层、用例层。
工具层放与业务无关的公共能力,比如YAML读取工具、时间处理工具、随机数据生成工具、加解密工具,这类代码从框架里剥离出来,任何一层都能引用。核心层是框架的心脏,请求会话封装、配置管理、断言引擎、测试数据加载都在这一层。业务层是针对被测系统做的接口封装,比如登录接口、订单接口、支付接口,它们把接口的URL、请求头、必填参数这些细节都封装固定下来,用例层不需要关心这些细节。用例层就是真正管理测试用例的地方,包括测试脚本和测试数据文件。
这样分层最大的好处是依赖方向是单向的,用例层只依赖业务层,业务层只依赖核心层,核心层只依赖工具层。修改底层实现不会影响上层逻辑,新增用例也不需要动核心代码。我接手过的那些彻底烂掉的框架,几乎都有一个共同特征:所有代码混在同一个目录里,请求逻辑和业务逻辑绞在一起,用例里面直接调requests,改一个接口的鉴权方式要全局搜索替换,最后只能推倒重来。分层这件事,宁可一开始多花点心思,也不要等代码量上来之后后悔。
2. 核心模块解析:请求封装、数据驱动与断言设计
2.1 请求会话封装:不只是一个requests库的壳
不少初学者理解的请求封装就是写个函数包一下requests.get,这个理解如果停留在这一层,框架的工程化程度就始终上不去。请求会话封装真正要解决的是三个问题:统一鉴权、统一日志、统一异常。
先说鉴权,这是封装价值最明显的一块。如果系统用token鉴权,你在每条用例里手动调登录接口拿token再拼到请求头里,用不了几十条用例就会发现痛苦不堪。正确的做法是在会话层做自动登录,把token缓存到会话对象里,后续所有请求自动带上,token过期后还能自动刷新。requests库的Session对象天然支持跨请求保持cookie和header,我们只需要在Session基础上做一层业务包装即可。
再说日志。每一次请求的方法、URL、请求头、请求体、响应状态码、响应耗时、响应体都应该被自动记录下来,不需要在用例里额外打任何日志。这样用例失败时,你打开日志文件就能完整还原当时的请求上下文,而不是靠猜。顺序上建议先记请求再发请求,否则如果请求超时,请求报文就会丢失,排查问题会很费劲。响应体日志建议截断存储,一次性打印几千行响应的大对象,日志文件会迅速膨胀,找问题的人也容易被淹没在无效信息里。
异常处理同样在会话层完成。网络超时、连接失败、响应不是合法JSON、服务端返回5xx,这些情况都要在会话层捕获并包装成框架自己的异常类型,附上清晰的业务上下文再抛出。如果你让requests的原始异常直接冒泡到用例层,报告上显示的信息永远是一行没人看得懂的堆栈,研发不会因为这种报告提起干劲。
2.2 数据驱动:从Excel到YAML的演进
数据驱动是接口自动化测试框架的核心思想,大白话就是测试脚本和测试数据分离,一条测试逻辑配多组测试数据,实现一脚本多用例的效果。什么数据放脚本里、什么数据放外面,这个边界要把握好。通常做法是请求参数、预期结果放到数据文件里,而业务操作流程留在用例脚本里。
早期很多团队用Excel管理测试数据,一行一个用例,列分别是接口名、请求方法、请求参数、预期状态码。Excel的好处是业务同事也能参与维护,但坏处随着时间的推移会越来越明显:版本管理困难,两个人同时改一个文件就会产生合并冲突;复杂嵌套结构表达吃力,一个订单请求体多层嵌套,在表格里几乎没法看;执行逻辑也不直观。
这些年我越来越倾向于用YAML来管理接口测试数据。YAML天然支持层级嵌套,一个完整的请求体可以表达得清晰直观;注释友好,能方便地给每条用例写上业务描述;最关键的它是纯文本文件,进Git后diff和review都非常轻松。一个典型的YAML用例大概长这样:
test_login_success: description: 登录成功场景 method: POST url: /api/v1/auth/login headers: Content-Type: application/json body: username: "test_user" password: "123456" expected: status_code: 200 jsonpath: - expression: "$.data.token" not_empty: true这里有个细节值得特别说明:expected字段不要只设计一个status_code,一定要预留jsonpath列表结构,这样可以同时做多个维度、多个字段的断言。一个用例只验证状态码等于200,那它跑一千条也发现不了业务逻辑问题,这一点放到断言设计里详细说。
2.3 断言体系设计:覆盖业务规则而不只是状态码
断言设计是接口自动化测试里最容易做浅的环节,同时也是最影响用例价值的环节。如果一套用例断言设计得很浅,跑得再勤快也发现不了真正的业务缺陷,那这套自动化就失去了意义。
我习惯把接口断言分成四个层次。第一层是协议层断言,检查HTTP状态码和必要的响应头,这一层最基础,但只做这一层远远不够。第二层是结构层断言,用jsonschema校验响应体的结构、字段类型,核心目的是防止接口字段被悄悄修改,这类问题在接口文档更新不及时的团队里经常发生。第三层是业务层断言,用jsonpath提取关键字段值和预期数据比对,或者校验字段之间的逻辑关系,比如下单成功后返回的总金额必须等于商品单价乘以数量。第四层是数据库层断言,在需要的时候直接查库验证数据落库是否正确,通常用在支付、订单这类数据一致性要求高的链路上。
实践里我的分配原则是:业务层断言是底线,核心场景必须有;结构层断言在核心接口上做,防止返工;数据库断言只在关键业务链路上做。数据库断言每加一条,执行耗时就会增加不少,而且会对测试环境造成额外的查询压力,所以一定要克制。断言层级的思路想明白以后,断言引擎的代码结构也就清晰了,把各层逻辑收敛到引擎统一执行,用例层只负责声明断言数据。
2.4 环境管理与配置隔离
接口自动化的用例跑到一定阶段,一定会碰到环境问题。开发环境、测试环境、预发布环境的接口地址不同,数据库不同,有些甚至连鉴权方式都不一样。如果这些配置硬编码在用例代码里,切换一次环境就得改一轮代码,这种框架基本没法用。
环境管理我推荐这样设计:项目根目录下建config目录,放一个公共配置文件存放所有环境都相同的配置,再按环境拆分差异配置,运行时通过环境变量指定当前激活的环境。命令可以设计成--env=test这种方式,框架启动时加载公共配置,再用环境配置里的值覆盖默认值。
# config_test.yaml env_name: test base_url: "http://test-api.example.com" db: host: "10.0.0.15" port: 3306 request_timeout: 15配置加载逻辑要放在框架初始化最早的位置,并且在加载完成后立刻做校验,比如base_url非空、db配置完整。宁可启动时报错,也不要让用例跑到一半才发现配置有问题。这个习惯在接入CI流水线之后尤其重要,流水线上的执行没有人实时盯着,配置错误导致的一堆假失败会非常打击团队的信任感。
3. 从零到一:一套可落地的框架搭建实操
3.1 项目目录结构设计
思路讲完,进入实操环节。下面这个目录结构是我最常用也最通用的一个版本,足够支撑多数业务场景的接口自动化测试,大家可以在基础上增删调整。
api_auto_test/ ├── config/ │ ├── config.yaml │ ├── config_test.yaml │ └── config_prod.yaml ├── core/ │ ├── session.py # 请求会话封装 │ ├── config_manager.py # 配置管理 │ ├── assert_engine.py # 断言引擎 │ ├── data_loader.py # 测试数据加载 │ └── report.py # 报告生成 ├── apis/ │ ├── __init__.py │ ├── auth_api.py # 认证相关接口封装 │ └── order_api.py # 订单相关接口封装 ├── testcases/ │ ├── test_auth.py │ ├── test_order.py │ └── data/ │ ├── auth_data.yaml │ └── order_data.yaml ├── utils/ │ ├── yaml_util.py │ ├── time_util.py │ └── random_util.py ├── logs/ ├── reports/ ├── requirements.txt ├── conftest.py └── pytest.ini这个结构对应前面说的四层划分:utils是工具层,core是核心层,apis是业务层,testcases是用例层。config目录集中管理配置,logs和reports分别放日志和报告输出,conftest.py放pytest的fixture,pytest.ini放pytest运行参数。整个结构的原则是:目录职责单一、依赖方向清晰、新同事进来之后不需要太多解释就知道什么文件该放哪里。
3.2 会话封装与断言引擎的实现
先看请求会话封装,这是框架里复用价值最高的代码。我会创建一个ApiClient类,在构造函数里创建Session对象,提供login方法用于统一登录,再提供一个request方法统一处理所有请求的收发和日志记录。核心逻辑如下:
import logging import time import requests from requests import Session logger = logging.getLogger(__name__) class ApiClient: def __init__(self, base_url: str, timeout: int = 15): self.session = Session() self.base_url = base_url self.timeout = timeout self.token = None def login(self, username: str, password: str): resp = self.session.post( f"{self.base_url}/api/v1/auth/login", json={"username": username, "password": password}, timeout=self.timeout, ) resp.raise_for_status() self.token = resp.json()["data"]["token"] self.session.headers.update({"Authorization": f"Bearer {self.token}"}) def request(self, method: str, path: str, **kwargs): url = f"{self.base_url}{path}" kwargs.setdefault("timeout", self.timeout) logger.info("请求: %s %s", method, url) logger.info("请求参数: %s", kwargs) start = time.time() resp = self.session.request(method, url, **kwargs) cost = round((time.time() - start) * 1000, 2) logger.info("响应状态码: %s, 耗时: %sms", resp.status_code, cost) logger.info("响应体: %s", resp.text[:2000]) return resp这段代码看起来简单,但要注意两个容易被忽略的细节。第一个是响应体截断,resp.text直接打全量,遇到分页接口那种几千行的响应,日志会直接爆掉,所以限制在2000个字符是比较稳的经验值。第二个是超时参数,kwargs里setdefault设置默认超时,确保每次请求都不会因为忘记传timeout而无限等待。
再看断言引擎。我的做法是定义一组断言类型,由引擎统一解析执行,用例只声明断言数据。下面的代码实现了一个最简版本:
import jsonpath from jsonschema import validate def run_assertions(resp, expected: dict): assert resp.status_code == expected.get("status_code", 200) for check in expected.get("jsonpath", []): expression = check["expression"] result = jsonpath.jsonpath(resp.json(), expression) if "expected" in check: assert result[0] == check["expected"], ( f"字段 {expression} 断言失败: " f"期望 {check['expected']}, 实际 {result[0]}" ) if "not_empty" in check: assert result and result[0] not in (None, ""), \ f"字段 {expression} 不应为空" if "schema" in expected: validate(instance=resp.json(), schema=expected["schema"])实际项目里的断言引擎会比这个复杂,可能会增加正则断言、大小比较、自定义回调函数等能力,但设计思路是一致的:把断言逻辑从用例里抽出来,收敛到引擎统一执行。这样断言规则变更的时候只改引擎一个地方,而不是去翻几十个用例文件。
3.3 pytest集成与用例组织
pytest的fixture机制是它适合搭接口自动化框架的关键原因。fixture用来管理登录状态、准备测试数据、清理测试数据,作用域可以控制得非常精细,session级别只初始化一次,function级别每条用例独立执行。
我在conftest.py里一般会定义一个session级的client fixture,整个测试会话只创建一个ApiClient实例,避免每条用例都登录一次,能省下大量执行时间。再定义一个函数级的cleanup fixture,负责在每条用例结束后清理产生的数据。一个典型的用例长这样:
import pytest_check as check def test_create_order(client, order_data): resp = client.request( "POST", "/api/v1/orders", json=order_data["request"]["body"], ) assert resp.status_code == 200 order_id = resp.json()["data"]["order_id"] check.is_not_none(order_id) client.request("DELETE", f"/api/v1/orders/{order_id}")清理动作我习惯直接写在用例里,而不是用独立的teardown函数,原因是可以精确控制清理时机,而且用例逻辑一眼能看全。如果造数据和清数据逻辑特别复杂,再考虑抽成fixture用yield的写法统一管理。顺带说一句,软断言库pytest_check值得引入,它能让一条用例里的多个断言都执行完,不会因为第一个失败就跳过后面所有检查,这样一次跑下来能发现更多问题。
3.4 测试报告与日志体系
没有一份像样的测试报告,自动化测试就很难说服研发配合修问题,这是我反复强调的一个观点。报告不需要多花哨,但要能回答三个问题:总共跑了多少用例、失败了几条、失败的用例挂在哪个接口的哪个断言上。
我的方案是pytest-html插件加自定义日志。pytest-html开箱即用,在pytest.ini里配置参数就能每次执行后自动生成HTML报告。为了让报告更有说服力,我通常会在conftest.py里通过pytest_html的钩子函数把每个用例的请求和响应信息追加到报告中,研发打开报告就能直接看到失败时的请求报文和响应内容,不用再去翻日志。
# pytest.ini [pytest] addopts = -v --html=reports/report.html --self-contained-html testpaths = testcases日志体系用Python标准库logging就能满足,配合RotatingFileHandler按大小滚动,按天归档,保留最近七天。我反复强调日志要打在会话层,因为那是所有请求的必经之路。日志散落在各条用例里,很快就会出现该记的没记、不该记的刷屏这种混乱局面。还有一点要注意,CI环境里控制台日志可能会被截断,建议把完整的日志落到文件里,分析历史执行结果时才知道当时到底发生了什么。
4. 接口自动化测试框架搭建的常见问题与排查技巧实录
4.1 接口依赖与数据准备的坑
接口自动化做久了就会明白,最大的敌人不是框架本身的代码,而是脆弱的测试数据。业务接口的上游依赖往往很复杂,创建一个订单可能要先有用户、有商品、有优惠券,而这些数据又很难稳定存在环境里。这类问题不解决,用例就会动不动失败,而且失败原因还不是业务bug。
针对数据准备,我有三招。第一招是数据准备脚本化,凡是能通过SQL直接构造的数据就不要一遍遍调接口去创建,速度快且稳定;第二招是场景类用例采用链式调用,把上一个接口返回的关键值提取出来作为下一个接口的入参,通过变量机制解决数据传递;第三招是数据清理自动化,每条用例执行后删除自己创建的数据,保持环境数据稳定,避免脏数据越积越多拖垮整体执行。
这里有一个我真实踩过的坑。有一次订单模块的用例不断在测试环境创建订单,跑了将近一个月,数据库里积累了几十万条脏数据,分页接口响应越来越慢,超时用例越来越多。一开始排查方向完全错了,以为是接口性能退化,后来定位到是自动化测试自己制造的数据污染。从那以后,凡是会写数据的用例,我都在用例里补上删除逻辑,一条都不能漏。
4.2 断言误报与稳定性问题
接口自动化用例挂得最多的其实不是功能缺陷,而是环境问题导致的误报。测试环境网络抖动、下游服务没有启动、定时任务跑批造成的数据状态变化,都会让一批用例集体变红。误报率高了之后,团队会对框架逐渐失去信任,最后框架就会被弃用。一个稳定性不可靠的自动化体系,不如不做。
降低误报率,我的经验是三层防护。第一层在会话层做请求重试,针对网络超时这类瞬时错误自动重试一到两次,注意只对幂等请求做重试,写操作重试要格外谨慎。第二层在断言层区分服务问题和业务问题,先确认接口能正常响应,再做业务断言,避免下游服务异常时产生一批无意义的业务错误。第三层是在用例集执行前跑一个环境健康检查,检查被测服务和其他关键依赖是否可用,环境有问题直接终止执行,而不是让几百条用例全部误报。
这套方法解决过我们一个很实际的困扰。以前每次跑完回归测试,聊天群里一片红色,研发看一眼就说环境问题吧,然后置之不理。加上健康检查前置以后,环境真的有问题时执行会被直接阻断,剩下的红色报告每一行基本都对应一个真实问题,说别人服气的底气完全不一样了。
4.3 框架扩展与维护的那些建议
框架搭建完成后,真正的考验是维护。我见过不少框架,初期搭建的时候热情高涨,代码越写越多,后来维护的人一换,慢慢就没人用了。框架能不能长期活下来,我认为关键在两点:模块职责边界是否清晰、变更成本是否可控。
维护期有几件事必须长期坚持。第一,业务层的接口封装要与后端接口文档同步更新,后端接口变更时第一时间改封装和对应测试数据,拖得越久欠的债越多。第二,新增用例必须写好description,说明这条用例验证的业务规则,方便后来人理解和维护。第三,核心代码的变更必须走评审,核心模块的接口签名尽量保持稳定,不要因为个人喜好频繁改动。
这里分享一个被验证过很有效的方法:把框架代码和业务用例分开管理,框架本身打包成私有依赖库,业务项目通过指定版本号来引用。这样框架升级和业务用例维护互不干扰,框架的改进还能同步惠及所有使用它的业务模块。最初做的时候也许觉得流程重,但项目多了以后收益非常明显,也不用担心核心框架代码被业务项目改得面目全非。
4.4 问题排查清单速查
最后整理一份问题排查速查表,这些都是实际运维中最常见的情况,直接照着排查能省掉不少时间。
| 症状 | 可能原因 | 排查思路 |
|---|---|---|
| 所有用例都失败 | 环境不可用或基础配置错误 | 先看健康检查结果,确认被测服务是否正常 |
| 只有登录相关用例失败 | 鉴权信息过期 | 检查token刷新逻辑,确认是否被异常用例污染 |
| 偶发超时 | 网络波动或下游服务变慢 | 看请求耗时日志,判断是否为瞬时问题 |
| 同一用例时过时不过 | 测试数据被其他用例修改 | 检查用例之间是否存在数据耦合,清理数据是否遗漏 |
| 响应体解析报错 | 接口返回结构变更 | 对比接口文档,检查是否新增了必填字段或调整了类型 |
这张表建议打印出来贴工位上。遇到用例失败,先按表格里的思路过一遍,能过滤掉一半以上的环境类问题,剩下的才是真正需要开发介入的缺陷,沟通成本也会低很多。
5. 从单接口到业务链路:框架的进阶之路
5.1 接口依赖传递与数据复用
框架搭完、单接口用例跑通,这只是开始。真实的业务场景里,很少有功能只调一个接口就完成。用户下单这个动作,背后可能涉及登录、创建订单、查询库存、支付、查询订单状态等一串接口的前后调用。单接口用例覆盖得再好,链路不通也是白搭。
所以框架到了一定阶段,必须支持接口之间的依赖和数据传递。我的做法是设计一个全局变量存储机制,允许用例从响应中提取字段值存起来供后续用例使用。比如登录接口返回的token保存为global.token,创建订单接口返回的order_id保存为global.order_id,在YAML数据里通过${global.order_id}这种引用语法来使用,框架在发送请求前完成渲染替换。
实现这个机制有两点要特别注意。第一是变量作用域和命名规范,全局变量跨用例传递,如果命名随意、生命周期不清晰,用例执行顺序一变数据就全乱套了,所以变量名要统一命名空间,并且在使用前检查是否存在。第二是渲染时机,变量替换必须发生在请求发送前,但断言阶段也可能引用同样的变量,两处都要支持渲染,实现时要统一处理。
5.2 数据工厂:解决接口自动化测试的数据供给问题
讲到链路测试,绕不开数据工厂这个词。数据工厂的本质是把测试数据的准备做成一个可复用的模块,测试用例需要什么场景的数据,直接调数据工厂去拿,而不是在用例里堆一堆前置操作临时去造。
我经历过一个非常痛苦的项目,创单接口的前置条件极其复杂,需要有一个已认证用户、一张可用的优惠券、一个库存充足的商品。一开始我们每条用例前面都写了几十行setup代码,结果用例执行时间有一半花在造数据上。后来做了数据工厂,把前置条件的构造逻辑收敛到一个模块里,通过参数化配置组合生成不同场景的数据,用例里的setup代码大幅缩减,执行速度也快了很多。
数据工厂的设计核心其实很简单,就是让创建数据能力从用例中剥离出来,变成一个独立模块。但它有三个质量要求,缺一不可:幂等,同样的参数调用多次结果一致,不能产生重复数据;可控,需要的场景可以精确配置生成;可清理,生成的数据能用统一接口删除,不留垃圾数据。这三点做好了,数据工厂就能成为框架里最省心的一块。
5.3 接入流水线与质量门禁
自动化测试的价值真正落地,必须跑在流水线上,并且形成质量门禁。每次代码提交之后流水线自动触发接口回归,测试通过才能进入下一环节。这个过程中框架必须支持无人值守执行,并输出可被程序识别的结果。
接入流水线要解决三个问题。第一是执行入口,框架必须提供纯命令行的执行方式,保证在Linux容器里也能正常跑,不能依赖图形界面或者IDE。第二是结果反馈,测试报告要能被流水线工具解析,最直接的做法是让框架在测试失败时返回非零退出码,同时生成JUnit XML格式的结果文件,Jenkins、GitLab CI这些工具都能原生识别。第三是环境隔离,流水线环境要用独立的配置文件,不能复用测试人员本机的配置,避免环境差异造成的结果偏差。
这三件事做完,接口自动化测试才真正成为研发流程的一部分,而不只是测试团队自己的工具。每次代码变更到这个环节,该拦住的风险就被拦住了,这个价值是单纯手工回归给不了的。
5.4 框架演进的一些个人心得
接口自动化测试框架搭建,说到底是测试工程化的一个缩影。以我这些年总结下来的体会,一个框架好不好,不取决于技术栈多新、代码多花哨,而取决于团队里有多少人在持续使用它,它帮助团队挡住了多少线上问题。一个简单但每天都在跑的框架,远胜于一个炫酷但慢慢没人维护的框架。
经过前后几轮框架迭代,我总结出几条做事的底层原则。面向变更设计,每个模块都要能回答两个问题:接口变了要改哪里,需求变了要加什么。面向团队设计,代码的可读性大于炫技,注释和文档要跟得上,不能让框架变成只有搭建者自己能懂的私有产物。面向长期维护设计,核心模块保持稳定,扩展通过配置和插件方式完成,尽量避免为了满足短期需求在核心模块里打补丁。这些原则真正做到之后,框架才不会成为一个负担,而是真正成为团队质量保障体系里最踏实的一环。