写点什么

基于 JSX 的全新 BDD 工具 - Crius

  • 2021 年 12 月 14 日
  • 本文字数:2181 字

    阅读完需:约 7 分钟

作者介绍—Michael

RingCentral Integration Frontend Tech Leader

曾担任若干公司前端负责人,擅长前端架构设计与 JavaScript 通用化,

对前端框架设计与自动化测试框架设计有深入研究及实战经验。


BDD(behavior-driven development)是 TDD(test-driven development)一种拓展。它强调定义明确的软件预期行为,通过用自然语言书写非程序员可读且包含软件行为和预期结果的测试用例,以此来扩展 TDD。

动机

从典型 BDD 开发流程上来看,大多先从基本的产品需求变成 Epic,再变成 User Story,最后细化成 Acceptance Criteria。而 Acceptance Criteria 形成的 Feature 文件通常定义了测试与产品功能的紧密关系。在 Acceptance Criteria 这层变得至关重要,我们试图探索出更好模型来契合越发复杂的功能需求与测试验证。从 2008 年至今,Cucumber 带来一些 BDD 上的革新与实践。大部分其他的 BDD 工具都或多或少借鉴了 Cucumber 的优点和模型。其中通过 DSL(Scenario, Given, When 和 Then)的字符串匹配模式便是一个重要特性。大量的字符串匹配带来的除了部分的性能损失和匹配唯一性以外,更重要的是在强调测试更深入的结构化时,就不可避免对其进行再设计和封装。随着开发应用系统的测试复杂度上升,无论是集成测试或 E2E 测试都常需要更清晰简洁的测试模型设计,以便于实践更具有可维护性的 BDD。在不断地 BDD 实践中,我们发现 Cucumber 有以下几个亟待解决的缺点:


  1. 字符串模式匹配

  2. Features 和 Steps 之间的隐式链接

  3. 缺乏 Scenarios 或者 Steps 可重用的简单方式这些缺点最终导致了 Crius 的出现。

什么是 Crius

Crius 是一个基于 Step 的 BDD 构建工具。它以 JSX 为 DSL 主要表达方式,所有软件行为和预期结果均可被定义为 Step,而声明式 Step 设计便于快速构建测试逻辑。


Crius 的演示代码:


@autorun(test)@title('User add ${todo} item in todo list')class AddTodoItem extends Step {
// cucumber-like example table, with JavaScript literals @examples` | todo | object | | 'learning' | { obj: 'literal' } | | 'crius' | { obj: 'hello' } | `
// which is equivalent to // @examples([{ // todo: 'learning', // object: { obj: 'literal' } // }, { // todo: 'crius', // object: { obj: 'hello' } // }])
run() {
// JSX-like declarative feature description return ( // explicit reference to actions <Scenario desc='User login website' action={Login}> <Given desc='User navigate to todo list' action={Navigate} />
{/* Allow Step class AddTodo to be used as an action to promote re-use */} <When desc='User type ${todo} in input field and click "add" button' action={AddTodo} /> <Then desc='User should see ${todo} item in todo list' action={CheckTodo} />
{/* 'action' props is optional */} <Then desc='Just an description' /> </Scenario> ) }}
// Functional Step definition similar to Functional Components in Reactconst Login = async () => { // actual code to perform login};
const Navigate = async () => { // navigate to todo list}
// Step is similar to React Component classclass AddTodo extends Step { async run() { return ( <> <TypeTodoText text={this.context.example.todo} /> <SubmitTodo /> </> ); };}
const TypeTodoText = async (props) => { // `props.text` is the todo text.}
const SubmitTodo = async () => { // click the "add" button};
const CheckTodo = async (_, { example }) => { // check todo item};
复制代码

特性

  • 声明式和富有表现力的 DSL - Crius 结合了 Cucumber 和 React 的 DSL 特性

  • 可重用的 Step 定义 - 提供更好的 Step 和 Scenario 组合

  • Step 生命周期 - Step 支持生命周期 Hooks,以加强对测试的控制

  • 插件式 - 允许轻松添加更多自定义功能

  • 适配各种测试框架 Runners - Crius 可适配 Jest, Mocha 和 Jasmine 等各种测试框架

  • 灵活的 Example 参数形式 - Examples API(@examples)支持 Array 和 Template literals

  • 轻量级库 - 核心源码小于 17k


与 Cucumber 相比,Crius 具有以下优势:


  • 非字符串匹配模式 - 通过直接引用 Feature 定义和测试 Step 之间的显式关系

  • Feature 文件即 JS/TS 代码 - 无需额外工具检查,默认支持 JS/TS 的 IDE 均开箱即用, 且在 IDE 和 Diff 工具中语法突出显示

  • 可拓展的 Hooks 和 Plugins - 可自定义各种测试解决方案以满足项目需求

  • 良好的 TypeScript 支持 - Crius 基于 TypeScript,它同时支持 JavaScript 和 TypeScript,IDE 自带智能提示和类型检查避免拼写错误

结论

Cucumber 为 BDD 带来了富有表现力的 DSL,并推广了这种做法。Crius 旨在通过为 Feature 定义和 Action 之间提供显式和清晰的关系,以及能更好地集成当前各种主流开发工具,同时也让组成 Action 的 Step 具有良好的可复用性。开发人员可根据自己的需求自定义其各自的工作流。我们相信,将 Crius 引入我们的工具集将大大提高软件的整体可维护性和质量,并提高 Stakeholder、PM、QA 和开发人员等角色之间的沟通效率。我们将持续迭代 Crius,引入更多的分析和协作工具,以进一步提高我们的工作效率和软件质量。


发布于: 3 小时前阅读数: 7
用户头像

还未添加个人签名 2021.11.24 加入

全球云商务通信与协作解决方案领导者,连续七年荣膺Gartner UCaaS(统一通信即服务)魔力象限全球领导者。与你分享各种技术专家的文章、公开课,各种好玩有趣的活动与福利,以及最新的招聘机会。

评论

发布
暂无评论
基于JSX的全新BDD工具 - Crius