无需了解TypeScript即可使用Playwright和TypeScript:一名工程师、一层AI功能以及四道关卡。
拥有Selenium和C#经验的QA工程师在AI辅助下用TypeScript构建了Playwright框架:包括结构、架构规则、钩子函数以及四个任务关卡。
来源: I Built a Playwright Framework in TypeScript Without Knowing TypeScript — Using AI
一个可以克隆的仓库,其中包含技能与规则,还有由MCP驱动的Playwright能够独立遍历应用程序——这样的承诺很容易做出,但实现起来却十分缓慢。实际上已经有一个可运行的项目存在:克隆它,执行一条命令,测试就会在真实网站上运行。它的起源源于一套旧有的测试套件以及关于编程语言的疑问。
那次从未获批的迁移
一个质量保障团队花了四年时间来维护那套旧的Selenium测试套件,后来转到开发岗位的一些同事了解它的时间甚至更久。这套套件的核心是数千个C# UI测试,这些测试是由早已离开公司的开发人员逐年积累下来的。将测试工具换成Playwright早已被列入愿望清单——它更快、更稳定,使用起来也更便捷,但最终还是没有实现这一转变。
原因其实很平常:没人愿意投入上百小时的工程时间去重写一个毫无商业价值的东西,而经理也不可能仅仅因为“新工具用起来更顺手”就批准这项工作。技术上的理由总是找得到,但工具套件越庞大,迁移成本就越高,其带来的收益看上去也就越微不足道。重写工作必须一次性全额支付费用,其回报永远不会以数字形式出现在报告中,而是体现在几年间故障测试减少以及问题更快得到解决上。因此这个想法就被搁置了。Playwright和TypeScript不断出现在越来越多的招聘广告中,而什么都不做对项目和个人来说都会变得越来越昂贵。
接着另一个团队开始了一项全新尝试,彻底重头开始:没有历史包袱,没有必须不能出错的庞大测试体系,也不需要为迁移找借口。由于有开发UI和API自动化的需求,Playwright与TypeScript终于被引入到日常工作中。但这同时也暴露了一个令人不安的事实:虽然Java和C#很熟悉,背后还有十年的测试代码作为支撑,但这里涉及的是测试而非开发,两者的深度截然不同。JavaScript、TypeScript以及Playwright本身都是全新的技术。一个在两年前还只是 rhetorical 的问题出现了:在人工智能盛行的2026年,不懂这些语言会在多大程度上限制一个人的发展?
这项实验的起源
这一转变并非由某一天突然触发,而是随着人们逐渐意识到仅靠测试和编写测试用例无法取得任何成果而逐渐形成的。质量保证工作的价值并非体现在缺陷数量或代码行数上,而是通过流程、文档、自动化工具以及沟通手段来提升产品质量;多年来,系统化的方法始终比个人的英雄主义更有效。
有两股力量共同推动了这一变化。
有一个推动因素来自一个用 Python 编写的加密货币交易机器人,它是某个不懂 Python 的人通过 Claude Code 创造的。项目起初因首次成功而令人兴奋,但当代码变得超出任何人的理解范围时便走向崩溃,没人能解释测试为何失败或如何修复。这带来的教训是编写代码与构建系统之间的差距:虽然机器人能够运行,但却无法维护。项目中没有清晰的架构图,每次修复都会引发新的问题,人们只是反复描述症状而非寻找根本原因,导致代币不断消失。
另一股推动力来自日常工作中人工智能逐渐渗透到质量检测流程中的现象。相关试验涵盖了从任务分配到测试完成的整个流程,制定了模型必须严格遵循的规则,同时确保整个流程具有可重复性和可控性。同事们将人工智能当作更智能的搜索工具或代码生成器。几乎没人尝试将其封装在能够实现可预测性的系统中,这似乎是种浪费,因为正是系统化的部分才蕴含着价值。
正是这两股力量催生了Playwright项目,其出发点是一个假设:拥有扎实基础的工程师在人工智能负责打字的情况下能取得多大的进展?而且,如果不使用工程师不熟悉的语言编写任何代码,是否仍能构建出完整的测试框架?
为何选择TypeScript而非C#或Java
首先进行的检查是显而易见的:Playwright也有适用于C#和Java的版本,因此或许没有必要更换编程语言。事实证明,差异并不在于浏览器驱动部分——这一部分在所有平台上都是相同的,使用相同的API、选择器以及浏览器。差异在于测试的组织方式与运行方式。
在 JavaScript 和 TypeScript 中,Playwright 自带了原生测试运行器,支持并行执行、测试固定装置、报告生成以及自动追踪功能。而 C# 和 Java 则没有这样的工具。各团队只能使用现有生态系统中已有的测试框架,无论是 xUnit、NUnit、JUnit 还是 TestNG,Playwright 只为这些框架提供基础类,因此组织结构和并行处理功能都需要自行实现。这才是真正的限制:并非语法复杂或缺少某些方法,而是要重新构建包括并行处理、线程数据隔离、内部机制以及报告生成在内的所有功能,而这些问题早已有人解决,也应尽量避免。与之相对的,还有一个选项——以一种没人熟悉的语言提供现成成品。Playwright 是在 JavaScript 的环境中发展起来的,因此它是原生集成的一部分,而非外来补充。
“无需额外学习即可使用”究竟意味着什么
称这个项目是在毫无经验的情况下构建的,不仅不准确,简直就是谎言。我拥有十年的质量保证经验,曾从零开始搭建开发流程,并测试过各类系统,从网页应用和API到移动应用都有涉及。正是这些经验让项目不会在海量生成的代码中迷失方向。而TypeScript与Playwright这些技术则始终是隐藏的强大助力。
有几门课程起到了帮助作用。在之前的实验和这次开发过程中,有几门Anthropic的课程涉及设计智能体、串联技能以及为人工智能编写任务描述。这些课程补充了实践经验,但并未取代它。关键在于态度。这个项目并非出自某个随意要求进行测试的程序员之手,而是出自一位工程师——他向模型明确了规则、架构限制以及需要检查的内容,然后让模型在既定框架内运作,从而将混乱的交互转变为有序的过程。
一个框架,附带两个注意事项
在介绍其结构及决策之前,有两点需要说明。
首先,这个项目只是一个框架而非成品,可供人们取用、修改或拆解。它被分享出来是为了展示一种思路,而非宣称其已完美无缺。那些寻求现成工具的人会感到失望,而那些想要基于该模型构建人工智能系统的人则能找到所需。各个团队都有自身的限制、安全要求及集成需求,那种适合公开演示的设计,在企业级的单点登录、多因素认证、特殊的测试数据规则以及测试管理系统背后,往往还需要进行大量的修改。因此,代码背后的设计思路才是可移植的部分。
其次,所使用的工具非常简单。仅有每月20美元的基础订阅版的 Claude Code 作为代码编辑器,Visual Studio Code 也用作编辑工具,还有一个为 Playwright 配置好的 MCP 服务器,让模型能够自行探索应用程序;或许最重要的是,还需要一颗清醒的头脑和一些空闲时间。无需任何昂贵的企业级解决方案,没有复杂的基础设施,也不需要分布式测试运行器。所有操作都在普通笔记本电脑上完成,这正是关键所在:启动项目并不需要什么超乎寻常的条件,只需要了解要构建什么以及有构建它的意愿即可。
项目涵盖的内容及结构安排
测试目标是一个名为Toolshop的公共演示在线商店,专为自动化练习而设计。这个选择很重要:由于不是封闭系统,也没有业务背景,任何人都可以克隆代码库,通过一条命令安装依赖项,然后针对真实网站运行测试,无需创建账户或查阅文档。
该测试套件包含三十七个测试用例,其中三十四个通过,三个故意设置失败,以便展示失败时的情况。API测试用于检测服务器逻辑,UI测试用于检测界面,而混合测试则先通过API创建状态,再在浏览器中进行检查。这些测试足以展示架构,但对于产品覆盖范围而言远远不够,因为产品覆盖范围取决于具体产品及其业务风险,而非演示版本包含的测试数量。目录结构如下:
config/
env.ts // The only place where environment variables are read
timeouts.ts // Timeouts, also in one place
core/
run-user.ts // The user registered by this specific run
global-setup.ts // Register → UI login → data snapshot → download OpenAPI spec
global-teardown.ts // Cleanup after the run: remove favorites and the user
allure-labels.ts // Parses [Section / Subsection] from the test name into report structure
allure-categories.ts // Buckets for triaging failures in the report
api/
generated/schema.d.ts // Types generated from OpenAPI, never touched by hand
types.ts // Domain types derived from the schema
client.ts // openapi-fetch, paths and params checked by the compiler
contract.ts // Runtime validation of API responses against the schema
auth.api.ts // Typed clients on top of api/client.ts
pages/
base.page.ts // Base page class
components/ // Elements present on every page (site header)
auth/ // Page Objects for authorization pages
account/ // Account area: account, profile, favorites
shop/ // Catalog, product page, checkout
fixtures/
base.fixture.ts // All dependency injection, test/expect only imported from here
data/ // Strings and routes, so they don’t live inside tests
utils/ // Logger, reference data snapshot
tests/
auth/ // Everything auth-related in one folder
auth.api.spec.ts // API: login, token lifetime
registration.api.spec.ts
login.ui.spec.ts // UI: login form, errors, logout
catalog/
products.api.spec.ts
catalog.ui.spec.ts
cart/
cart.ui.spec.ts
favorites/
favorites.api.spec.ts
favorites.hybrid.spec.ts // Hybrid: state via API, verification via UI
profile/
profile.hybrid.spec.ts
contract/
contract.api.spec.ts // Matching live API responses against the spec
demo/ // Tests tagged @demo that fail on purpose
docs/ // Feature maps, checklists, test cases, plans
.claude/ // AI layer: rules, skills, agents, hooks```
可扩展的结构设计
- 先考虑功能,再考虑层级。某个初始选择看似奇怪,却决定了整体扩展性:测试按功能分组,层级则作为文件名后缀,例如
login.ui.spec.ts、auth.api.spec.ts和checkout.hybrid.spec.ts。当开发者修改授权逻辑时,只需在tests/auth/下查找所有相关测试,而无需在三个文件夹中逐一搜寻。测试数量为30个时几乎无人察觉,基于层级的结构显得井然有序;但一旦达到300个,tests/ui/就会变成包含60个文件的杂乱文件夹,因为只要某个功能被修改,无论其属于哪个层级,所有相关测试都会随之改变。分散的测试会让分析工作变成繁琐的搜索过程。
tests/auth/login/、tests/auth/registration/ 和 tests/auth/password-reset/,这延续了在代码旁保留相关上下文的理念。同样,数百个测试用例也不应共享同一个文件,因为那样会导致文件变得难以阅读和审查。决定其余内容的四个关键抉择
该仓库在 .claude/rules/architecture.md 中记录了十四项架构决策,每项决策都回答的是“为何如此选择”而非“这是什么”。此处重述了其中的四项,因为其余内容最好保留在仓库中,而非进行改写。
每次运行都会创建独立用户
通常的设置是所有测试共享一个测试账户。但当测试套件规模扩大且测试开始并行运行时,就会出现问题:一个测试正在清空购物车,另一个测试却检查其中是否有商品,从而导致失败,这种故障在二十次运行中才会出现一次,且绝不会在调试器所在的机器上发生。
这条规则听起来很枯燥:每次运行都会拥有独立的沙箱环境。这与承诺避免数据共享或事后进行整理有所不同。它的意义在于实际上不存在任何会相互冲突的元素。在公开演示中,通过在global-setup中注册的新用户即可完成这项工作。而企业环境可能会通过租户限制、共享实体或已存在的数据重建任务来阻止这种做法。核心原则依然成立,至于创建沙箱的具体方法则是另一个问题。
同样的逻辑也决定了 retries: 0。重试的作用只是掩盖问题而非提供保障:它会让真正的竞态条件被误认为是正常现象,从而将问题推迟到最严重的时刻才显现。需要重试的测试并非不稳定,而是报告了隔离故障,这样的报告值得深入分析。其成本十分明确:在演示环境中,注册用户只需一次请求且始终成功,而在其他环境中机制会有所不同。
类型来自规范,契约测试用于验证规范
这是两种经常被混淆的不同检查方式。
- 第一种是在编译时进行的。API拥有 OpenAPI 文档,类型就是从该文档生成的,因此如果代码中引用了但规范中不存在的字段,项目就无法编译。这一过程只需两秒,且无需向服务器发送请求。
products/{productId},而代码中使用的是products/{id}。还有一次,他们发现产品目录筛选功能调用了by_category_slug这个参数,而该参数根本不在规范中。由于服务器接受了这个参数且测试结果为正常,因此一切看似“正常运行”。但实际上,契约之外的参数绝不能偏离契约要求,它只能某天悄然消失。因此,契约测试并非用于检查某个接口是否正常工作,而是用来确认该接口是否与大家约定的规范一致。
有效期为三百秒的令牌
最初的设计是在运行前登录一次,将令牌保存到文件中,让所有工作进程都能读取。实际上也差不多是这么做的。但该 API 的令牌有效期恰好为三百秒,专门的测试通过比较令牌中的两个字段来验证这一点,而整个测试套件的执行时间比三百秒还要长。最慢的测试完成后,令牌会失效,导致 401 错误,这看起来像是权限问题而非过期问题,因此调试会从错误的方向开始。
因此,文件中存储的是凭证而非令牌。每个工作进程都在内存中持有自己的令牌,并提前进行更新。由此产生一个要求:必须在实际使用令牌的地方直接获取它,绝不能将其提取到代码块的顶部作为变量。只要有一行代码这样处理,就会重新引发设计初衷要解决的那个问题。
快照仅存储静态参考数据,绝不可存储可变状态
类别、品牌以及产品页面在多次运行之间不会发生变化。可以在开始前一次性获取这些数据并传递给测试用例,这样30个测试用例就无需各自请求相同的列表。而收藏项、购物车和用户资料则绝不能被纳入快照,因为这些内容本身会随着测试的进行而改变。对可变状态进行快照处理并非优化手段,它只会生成存在时间延迟的数据:测试用例读取的是5秒前的数据,从而导致测试失败,随后人们会在实际上并不存在问题的应用程序中寻找故障。
清理操作也遵循相同的逻辑。它会按顺序执行,先处理实体,再处理其所属对象,且永远不会失败;权限不足仅会引发警告。如果清理过程失败,一个原本正常的测试用例就会变成带有错误说明的失败运行,这是最糟糕的失败类型。
AI层
试想当 Claude Code 在项目文件夹中打开并收到“为购物车编写测试”这一请求时会发生什么。模型仅收到该请求,除此之外一无所知。它不知道共享账户是被禁止的,不知道定位信息必须来自经过验证的地图,也不知道在并行测试套件中对全局计数器进行断言是个陷阱。它会进行猜测,而且猜测得相当准确,因此生成的代码看起来不错,很可能也能运行。大多数人到此就认为这便是利用人工智能完成了工作。
人工智能层会对问题进行重新表述。问题不再仅仅是模型会做出什么猜测,而是它必须了解什么以及可能永远无法做到什么。这一层由五个组件构成,每个组件都有各自的任务。
- CLAUDE.md,始终会被加载。这是位于项目根目录中的文件,会在每次会话开始时被读取。它相当于为新同事(此处指模型)提供的入门指南,内容被浓缩在两个屏幕中展示:项目简介、各要素的位置、五个最重要要点以及明确禁止的内容。“始终”一词限定了其容量,因为每次对话都会根据上下文为该文件付费,只有每次都会用到的内容才会被包含在内。四十条风格规范则被放在另一个单独的文件中,通过链接方式引入。
.env文件是不可编辑的。git push --force、--no-verify和--amend命令会自动被拒绝。钩子既不会进行说服也不会事后解释,相关操作不会发生,系统会说明原因并给出正确的处理路径。简而言之:CLAUDE.md是新成员入门时必读的资料,规则是团队标准,技能是操作流程手册,代理是权限有限的实习生,而钩子则是始终处于关闭状态的关卡。
实时工单上的同一层级
抽象概念只有在实际任务经过它们时才有意义。以PROJ-431“通过卡片支付订单”为例,正常的处理流程与人工智能毫无关系:有人手动测试该功能,有人编写检查清单,有人将其转化为测试用例,还有人负责实现自动化。这些工作可以由一个人完成,也可以由三个人分工完成。对于流程而言,由谁来做并不重要,这正是其意义所在——因为该流程是叠加在现有流程之上的,而非取代它。任务编号是贯穿所有环节的线索,相比功能名或分支名更值得使用,因为它不会因重命名或任务重新分配而改变。
第一步:检查清单
质量保证工程师启动该技能并传入编号。由于MCP与Jira相连,该技能可直接读取工单内容,包括描述、验收标准,以及通常最有用的是那些开发者未更新描述却已解释部分功能的评论。如果没有MCP或工单为空,工程师则需要在提示词中描述该功能。该流程需要输入内容,且不关心其来源。
接下来就是一切构建工作的开始阶段。该工具并不会从任务描述中直接生成检查清单,而是会调出研究代理,让其进入应用程序的本地或测试环境,访问相关功能页面,点击各个元素,读取实时DOM内容,自行调用API,并将返回结果与规范进行比对。只有在此之后,才会根据实际存在的情况而非任务描述中的承诺来编写检查清单。验收标准只是输入信息而非客观事实,而这些标准与现实情况之间的差异,往往就是任务中最早出现的缺陷,甚至在代码编写之前就能被发现。
最终会生成两个文件,而将它们区分开正是此处最重要的要点。第一个是检查清单:以团队规定的格式列出优先级的业务场景,而非元素检查。某个字段带有红色边框并不代表它是场景,而使用他人卡片的用户被拦截并被告知原因则属于场景。第二个是功能映射图,其中包含已验证的位置标识、API字段、验证规则以及测试过程中发现的潜在问题。检查清单是任务的直接成果,而映射图则为后续步骤提供参考。质量保证工程师会阅读检查清单,删去不必要的内容,补充只有相关人员才知晓的信息,这一审核环节是一道关卡:未经确认不得继续下一步。
第二步:测试用例
执行了第一步的人可以继续进行,如果手动测试与自动化测试分开的话,则可以由其他人接手。第二种技能会使用相同的任务编号,自行查找检查清单和对应映射。工程师决定要覆盖哪些内容,可以是全部,也可以仅是已约定的部分。该技能会将这些项转化为测试用例,并为每个用例确定一项内容:即该检查所属的层级。
- 由服务器强制执行的规则会转化为API测试。
- 用户可见的内容会转化为UI测试。
- 某个断言需要15次点击才能完成设置的检查,则会转化为混合测试,通过API构建状态,仅对可见部分进行目视检查。
这里的错误带来的代价远高于编写不佳的用例,因为它们会导致覆盖范围缓慢且重叠,之后就没人敢删除这些内容了。该工具还会为每个用例添加服务部分:所需数据、定位信息、哪些内容必须唯一、哪些内容需要清理以及由哪个账户负责。对普通人来说这看起来像是一堆文书工作,但对后续流程而言却是现成的规范。工程师会进行审核并批准,这是第二道关卡。使用 Qase 或 TestRail 的团队可以在此添加相应功能,通过 API 上传已批准的用例,随后将其标记为自动化用例。
第三步:自动化
该自动化工具会获取任务编号,进而调取检查清单、相关案例以及地图数据。它的第一个操作出人意料:它会检查地图的更新时间。每个部分都有对应的验证日期,超过一个月的数据将不再被视为事实,而变成一种假设。该工具既不会直接拒绝,也不会盲目信任这些数据。它会将过时的信息移到计划中的风险部分,然后由人类决定是重新进行勘测还是接受该风险。过时的定位信息无论如何都会显示出来,但会在三步之后以“超时”形式出现,且超时的原因会被隐藏。
接下来是计划阶段:需要使用哪些文件、每项测试使用什么数据、运行前会创建什么内容、运行后会删除什么内容、要添加哪些页面和客户端方法,以及还存在哪些问题。该计划是第三个也是最重要的环节,因为它决定了该批任务是否可以安全地并行运行,而事后修改这一计划成本极高。
一旦获得批准,计划就会交给负责编写代码的智能体,它的特点是不自行创造定位器。如果映射表中缺少所需的定位器,它既不会猜测类似的定位器,也不会通过跳过测试来掩盖这一缺失。它会在代码中留下注释,说明该定位器尚未经过验证,并进行上报。虽然测试代码仍会被编写出来且测试会失败,但这其实是正确的,因为问题依然存在,并未得到解决。
过去需要分别执行的命令现在都包含在这一步中:运行、读取错误信息、修复。每项测试有两次尝试机会,之后代理就会停止并承认失败。一次顺序运行用于检查逻辑,两次并行运行用于检查隔离性。由于这些操作都不需要人工决策,因此无需额外的按钮。这只是一套写在规则中的流程。
这里的禁令是明确的,不容讨论:
- 不得禁用失败的测试以使运行结果显示为正常。
- 不得增加重试次数。
- 不得暗中削弱检查标准以使其符合观察到的行为。
如果应用程序行为异常,红色测试结果才是正确的。
第四步:审核并确认
代码审查与提交属于两项不同的技能,而非同一项——这是有意为之的区分,因为若一开始就带着提交的意图,反而更难找到不提交的理由。代码审查需要具备特定项目的相关知识,这是普通审查者所不具备的:这里的“共享实体”指的是什么,代码块顶部的“令牌”会带来什么风险,为何对全局计数器进行操作会导致误解。列表中的每一条记录都源自过去该流程出现的故障。为避免这种区分流于形式,代码审查会留下所审查代码差异的“指纹”,如果此后该差异发生了变化,提交操作就会拒绝继续。这并非真正的锁定,而是一个有明确答案的问题:这是经过审查的代码,还是其他代码?流程与习惯之间的区别就在于此。
当整个流程执行完毕后,PROJ-431会记录下全部信息:研究了什么、选择了什么进行验证、哪些部分由自动化处理、哪些仍需手动操作,以及哪些不会被自动化处理及其原因。这并非出于对文档编制的重视。六个月后,在回顾会议中会有人提出某个场景为何未被覆盖的问题,届时必须要有答案。
比任务更持久的东西
该方案的主要风险并非生成的代码质量差,而是六个月后上下文会变得混乱不堪,没人知道该信任哪个文件。因此,相关成果会存在三个独立的生命周期,且严禁将它们混为一谈。
- 规则会与项目一同存在,仅会随着代码的变更而调整。
- 特征图会长期存在,属于特征而非任务本身。它会通过添加带日期的章节、新页面以及新的注意事项来扩展,而不会因每个任务的出现而重新生成。
- 检查清单、案例和计划属于某个特定任务,当该任务完成后便成为历史记录。
如果没有进行那样的拆分,一年后定位图就会以十份的形式散布在各个任务编号中,其中一半是错误的,且无法分辨是哪一半。当某个特征的地图像大型特征的地图那样变得庞大时,解决办法与处理代码类似:需按照页面、子特征或场景等自然划分线将其拆分成若干部分,并在顶部列出简短的索引,标明各部分的内容位置。此外还有一条严格的输入规则:只有经过验证的事实才能进入地图,也就是代理在实时应用中实际看到的内容,并需标注日期;猜测和任务描述的内容则不可纳入。在迭代周期内,允许此类内容的地图就是无用的垃圾,而且事后也无法将事实与猜测区分开来。
这些都不是通用的解决方案。四个流水线步骤、五个AI层组件、控制门以及模型生命周期只是一种可能的组合方式。不同团队的成员数量、产品及工具各不相同,因此一半的细节处理方式也会不同。有些方法可行,有些需要调整,还有些则行不通,但这都是正常的。
核心原则始终不变:要正确构建AI层,让模型在团队范围内遵循团队的规则,并使用团队现有的工具;而那些常规工作则应从团队的任务清单中移除——比如阅读工单、编写类似案例、选择层结构、定位问题、重新运行并修复故障、反复检查同样的错误点。QA工程师不会被取代,现有的流程也不会被取消。时间只会花在那些可以移交出去的工作上。
还需要资深人员吗?
如今比以往任何时候都更需要高级工程师,而且他们的角色也发生了变化。David Heinemeier Hansson指出,他所见过的最有效的智能体驱动式加速效果源自那些最资深的工程师,他们能够判断智能体的输出是否适合使用。
过去,工程师的价值在于编写代码、掌握语法以及快速完成任务,因为在代码还是主要产品的时代,这确实很重要。但随着人工智能的出现,这种价值已经发生了根本性的变化,而非仅仅是几百分比的变动。机器负责编写代码,而人类则决定要写什么、为何而写、在何种限制范围内编写,以及如何验证结果是否准确。
想象两位专家。第一位打开 Claude Code,要求编写一个登录测试。测试被写出来并通过了,这位专家感到高效,这在今天确实如此。一个月后,测试出问题了,原因成谜,补丁被随意添加,同时代币也在不断消耗,最终所有内容都被重写,或者测试被删除并被人遗忘。
第二位专家则先进行设计:确定测试如何隔离、API 客户端遵循何种模式、代币如何管理,以及测试之间状态变化时会发生什么。只有之后才会给模型下达指令:根据这些规则编写一个登录测试。
第一种方式使用的是当前可用的测试工具。第二种方式则基于稳定的架构而非偶然因素来构建系统,因此能够持续运行。在少量测试时,两者之间的差异并不明显,只是第一种方式能在十分钟内完成十到十五项测试,而第二种方式仅完成基础测试就需要两小时甚至更长时间。但当测试数量达到一百、两百或一千次,管道运行次数达到五十到一百次时,两者之间的差距就变得十分明显了。
这是否意味着必须学习某种编程语言?
是的,但不是用于编写代码。需要一种语言来理解人工智能生成的成果,发现生成代码中的错误,审查拉取请求,并决定哪些内容可以合并到主分支。语法只是一种工具。对于身处陌生领域的测试人员而言,复杂的记忆结构难以驾驭,但架构则是熟悉的领域:系统应具备怎样的结构,如何保持测试的独立性,如何组织流水线,以及一份优秀的报告应包含哪些内容。正是这样的基础使得 Playwright 项目得以实现。
架构并非凭空产生。人工智能可以提出方案,有时还相当不错,但架构是在多种方案中做出的选择,而不仅仅是一个方案而已。模型可能会给出五个看似都合理的选项,但哪一个能在六个月的时间里、在测试数量增加十倍且需求发生变化的情况下依然适用,这是无法通过模型生成的。这些认知源自经验,源自解决那些反复出错的测试所积累的经验,源自弄清楚为何某个测试在本地能通过却在持续集成环境中失败,也源自发现那些隐藏着的、随时可能引发问题的共享依赖关系。
企业不需要那些只会在 Claude Code 或 Cursor 中点击按钮、输入提示词的人。这类人已经很多了,而且还会更多;市场上充斥着自以为发现了宝的初级程序员,但他们的优势只能维持很短时间。真正需要的是那些明白人工智能为何会做出某种行为、能察觉其错误、能够合理设定任务让模型给出可行解决方案而非仅是经过修饰的错误结果、并且懂得构建系统而非不断投入令牌进行“再试一次,不对”的循环的人。
流程处理、自动化及管道构建的经验并非过时知识,而是高效开展人工智能工作的基础,它能区分那些只会制造混乱的人与那些能够构建系统的人。过去,知识用于手动完成任务,而现在则用于为人工智能设定任务并检查结果。虽然角色发生了变化,但专业技能的价值依然不变。由于在人工智能的辅助下,谁只是单纯生成内容、谁理解生成内容及其背后的原因变得一目了然,这一点或许更容易被察觉。
实验揭示的内容
有人用一种自己并不熟悉的语言构建了一个框架,这并非关于天才的故事。而是一个关于不必试图猜测人工智能会做什么,而是花时间解释游戏规则的故事——什么可行、什么不可行,以及为何要这样而非那样做。这很枯燥,与氛围毫无关联,而且要过一段时间才能看到初步成果。但恰恰是这种方式行之有效。
这个代码库并不能证明工程师已经过时,也不能说明编程语言不再重要。它实际上是在验证:当价值从编写代码转向任务规划、系统设计以及结果验证时,工程师的角色会发生怎样的变化。手工编写代码依然是一项技能,如今又多了一项同样重要的技能:理解生成的内容、其背后的原因以及接下来的步骤。
人工智能不会取代工程师。它将成为最快捷、最听话的“初级员工”——不知疲倦、从不争论,且随时准备再次尝试。但它有个特点:会以同样的自信给出正确解法与完全无意义的答案,只有了解这项工作的人才能区分二者。因此,工程师必须继续掌舵,作为知晓目的地与路线的人,而非仅仅握着方向盘的人。
相关阅读
- MAF 1.0、LangGraph还是CrewAI?2026年选择智能体框架指南 ——对比Microsoft Agent Framework 1.0、LangGraph和CrewAI在状态管理、内存使用、调试功能、协议标准、Azure集成路径及成本方面的差异,并提供简短的决策路径与部署方案。