Yadda是知名BDD(行为驱动开发)库,3.0版本专门针对AI Agent场景重写,支持自然语言规格与机器可执行契约的双向映射。
Yadda 刚刚发布了 3.0.0 版本。
对不熟悉它的读者来说,Yadda 是一个面向 JavaScript 的行为驱动开发(BDD)库。与 Cucumber 类似,它将自然语言规格映射为可执行代码,但它从设计之初就不打算对规格的编写方式做过多的约束。
这意味着你可以写这样的步骤:
Given a university, The University of East Anglia
And The University of East Anglia offers a degree course in Computer Science with entry requirements of ABB
And an A-Level graduate, Steve
And Steve has a D in Physics
And Steve has a D in Maths
When Steve applies to study Computer Science at The University of Bouvet Island
Then The University of East Anglia rejects the application
也可以写成这样:
The University of East Anglia offers a degree course in Computer Science
The entry requirements for which are ABB
Steve is an A-Level graduate
With a D in Physics
And a D in Maths
When Steve applies to study Computer Science at The University of East Anglia
They reject his application
两者都是可执行的规格。我发现后者读起来要舒服得多。
Yadda 3 有哪些变化?
Yadda 3.0.0 大部分是一次现代化改造。
Yadda 存在的时间很长了,仓库积累了不少集成和工具,用以对接 JavaScript 生态中如今已经成为历史遗迹的那些东西。Yadda 3 改为仅支持 Node,移除了浏览器打包以及过时的集成如 CasperJS、PhantomJS、Bower 和 Component,测试套件迁移到 node:test,采用 Biome 和 lefthook,源码全面升级为 ES6 语法,新增了包括 Playwright 和 Puppeteer 在内的当前主流示例,并且现在开始附带 TypeScript 类型定义。
这些都很有用,但写出来算不上有趣。这个版本我认为有两点变化意义更为重大。
大部分代码是 Claude 写的
我借助 Claude Code(Opus 4.8)对 Yadda 进行了现代化改造。
Yadda 3.0 的史诗(同样由 Claude 撰写)将工作拆分为一系列刻意分离的阶段:移除过时功能、更新工具链、机械性的格式化与行为改动分开进行、现代化改造源码、探索 API 变更、更新示例和 CI,最后收尾元数据、文档和 TypeScript 定义。
每个阶段在实施前我们都先做规划,之后我就基本上让 Claude 自己干活了。它犯的错误少得惊人,更令人印象深刻的是,它还识别出了一些相当微妙的边界情况——这些在最初看起来只是一次机械性现代化的过程中很容易被忽略。我的干预非常少。
一个重要因素是 Yadda 本身已有了一套全面的测试套件。另外我刻意避免让 Claude 在同一步骤中同时修改生产代码和对应的测试。如果一个 agent 同时改了两者,测试变绿就变成了更弱的证据——因为它可以同时改变"正确"的定义来适配实现。将这些改动保持分离,让 Claude 拥有一个严格得多的外部约束。
从开始工作到包发布,大约经过了一天时间,而且这期间我还在并行做其他事情。
今年年初我写了一篇文章,探讨为什么 vibe coding 的体验两极分化得如此严重。彼时我的结论是,结果很大程度上取决于如何使用 agent。一个受到严格约束和监督的 Claude 可以非常快速地产出极佳的结果。如果放任自流,它就容易走向架构漂移、引入不必要的代码和运维债务。
距离那篇文章才过了七个月,能力已经发生了巨大的进步。即便如此,说 Claude 现在能在极少干预下写出这些代码,也仍然远远没有触及正在发生的变化的核心。
编程不再是瓶颈
要理解未来的走向,关键在于不再把一个开发者与一个编程 agent 的单独对话作为思考模型,而是考虑多个 agent 并行工作的场景。
现在已经有了好几种方式来实现这一点。你可以简单地在多个终端里同时运行多个 Claude Code 会话。Git worktrees 让每个 agent 都可以在一个独立的工作副本上操作。cmux 这类工具让管理一组 Claude 会话变得更加可行,而 Claude Code Agent View 提供了另一种方式来观察多个会话在做什么,以及哪些会话需要你关注。
所有这些都能让你比串行工作快得多地构建,但我很快又遇到了另一个限制:我自己管理并行工作的能力。我最多能同时舒服地推进三个任务,有时四个或五个。再多的话,我就会开始丢失对每个 agent 正在做什么的上下文记忆——哪些决策已经做出、哪个任务在等我、接下来需要审查什么。
到了那个点,模型没有过载,机器也没有过载。瓶颈是协调工作的人。我越来越坚信,好的编排是下一个重要的层次。
我并不是唯一一个得出这个结论的人。我的同事 Marco 在《My AI Engineering Journey》中描述了几乎完全相同的发展历程:从 AI 作为自动补全,到监督式和受信任的 agent,再到认知负载成为约束的并行 agent。他比我更走在前面,他的回应是构建了 Otto——一个围绕 Claude Code 和 worktrees 的编排 UI,随后又进一步构建了协调实现、审查、反馈和文档的 agent 管道。
更重要的一点是,AI 辅助的软件开发仍在以极快的速度发展。单兵的编程能力已经得到了显著提升,并行执行已经切实可行,下一个约束越来越变成对所有这些能力的协调。做这件事的工具和方法同样在飞速发展,如今它们甚至可以说比模型更新本身更重要。
这就把我带回到了 Yadda。
为什么现在要更新一个 BDD 库?
我一直认为 BDD 在几个方面是有价值的。
首先,用自然语言编写需求迫使你阐述领域,更重要的是促使你保持一致地阐述。如果你先写这些规格再写实现,这种领域语言就会自然而然地渗透到整个代码库中。相同的概念开始出现在类名、函数名、API 定义、数据库 schema、CSS 类和用户界面中。这给了代码库一种内聚力,而这种内聚力是事后很难达到的。
其次,可执行规格比传统的程序化测试更容易被接受。产品经理、业务分析师或领域专家有现实的机会理解这样的内容:
When Steve applies to study Computer Science
Then the university rejects his application
而让他们从一个包含 fixture、mock、builder 和 assertion 的 Jest 测试中提取出相同的含义,可能性就小得多。
第三,BDD 为功能测试提供了一个有用的抽象层。规格描述意图,而步骤实现则处理选择器、导航和浏览器交互等机械性细节。这提供了与 Page Object 模式部分相同的好处:用户界面的变更通常可以被吸收在抽象层内部,而不是渗透到数百个测试中。
但一直存在一个代价。BDD 测试初期需要更长的编写时间。你需要考虑语言风格、创建可复用的步骤,并且要抵制把 절차性脚本伪装成英语的诱惑。收益在后期才会到来——通过更好的领域建模、更好的沟通和更易维护的功能测试。这种延迟收益使得 BDD 一直更难证明其合理性,但我认为 AI 改变了这一经济账。
可执行规格是非常好的 agent 上下文
考虑一种越来越可行的工程工作流程。
会议自动转录并存为 GitHub 讨论区。这些讨论被分析后用于更新项目 wiki。Wiki 被挖掘出需求和问题。然后这些问题被一组编程 agent 拾取、实现、审查和协调。
Wiki 能告诉你某人认为系统应该做什么。它能告诉你系统过去做什么。它甚至能告诉你一个 agent 推断出系统应该做什么。但它本身无法告诉你系统实际上是否做了那些事。可执行规格可以。这使得在 agent 开发环境中,BDD 比以往有趣得多。
BDD 中成本最高的部分是产生和维护规格。AI 使这类工作的大部分变得廉价。转录、讨论或需求可以几乎毫无障碍地转化为候选规格,人类只需专注于语言和行为是否正确,而不必亲自把一切都打出来。一旦被接受,这个规格就不仅仅是文档了——它成了一份契约。
实现 agent 可以用它来理解所需的行为。测试 agent 可以用它来确定需要验证什么。审查 agent 可以用它来质疑一个实现。CI 可以持续验证它。因为它是可执行的,所以它与软件的行为保持着一种 wiki 页面永远无法做到的耦合。
这里有一个有趣的反转。BDD 的产生部分是为了让软件规格对人类更有用,但可执行规格可能在软件大部分由机器编写的时代变得更有价值。自然语言给予 agent 丰富的领域上下文,而可执行步骤确保规格始终锚定在系统的行为上。
另一个变化(添加在 Yadda v3.1.0)是支持将特性规格以 GitHub 风味的 Markdown 编写。这让它们在仓库中更容易阅读,更重要的是允许它们自然地与项目 wiki 以及人类和 agent 用来理解系统的其他关键知识制品共存。同一个规格现在可以这样写:
# Feature: University applications
## Scenario: Applicant does not meet the entry requirements
- The University of East Anglia offers a degree course in Computer Science
- The entry requirements for which are ABB
- Steve is an A-Level graduate
- With a D in Physics
- And a D in Maths
- When Steve applies to study Computer Science at the University of East Anglia
- They reject his application
它仍然是一个可执行的规格,但在 GitHub 上查看时,它看起来和行为都更像是项目文档的一部分。
Yadda 3 可以从 npm 获取,源码、文档和示例在 GitHub 上。