ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

@cypress/grep 指南:用标题子串与标签逻辑精准过滤、编排 Cypress 测试

@cypress/grep 指南:用标题子串与标签逻辑精准过滤、编排 Cypress 测试 cypress/grep 指南用标题子串与标签逻辑精准过滤、编排 Cypress 测试【免费下载链接】cypressFast, easy and reliable testing for anything that runs in a browser.项目地址: https://gitcode.com/GitHub_Trending/cy/cypress本指南以本仓库 npm/grep 目录下发布的cypress/grep包为核心其项目级说明见 npm/grep/AGENTS.md被 npm/grep/CLAUDE.md 通过AGENTS.md引入系统讲解如何按测试标题子串与自定义标签运行 Cypress 测试子集并覆盖 spec 级预过滤、测试燃烧burn、布尔标签语法与运行时过滤 API。读完本文你将掌握在命令行、cypress.config.ts、package.json脚本以及浏览器 DevTools 中组合使用 grep 过滤的完整实战方案并通过源码级剖析理解其底层实现原理。一、包定位为 Cypress 测试套件提供筛选与编排能力cypress/grep是一个已发布的 npm 包为 Cypress 提供测试过滤能力按测试标题子串或用户自定义标签运行测试子集并提供 spec 级预过滤与测试燃烧将测试重复执行 N 次以暴露偶发性不稳定/flaky 行为等选项。其主要能力包括按测试标题中包含的文本运行测试grep 过滤用自定义标签组织并运行特定测试分组tag 过滤预过滤 spec跳过不包含匹配测试的 spec 文件grepFilterSpecs测试燃烧重复执行匹配测试多次以捕捉偶发失败burn智能组合标题与标签过滤叠加精确定位测试从仓库结构看cypress/grep是 monorepo 中发布到 npm 的独立包源码位于 npm/grep/src包声明见 npm/grep/package.json。其根入口在浏览器 support 文件中加载cypress/grep/plugin子路径入口则在 Node 侧的setupNodeEvents中加载exports字段中.与./plugin分别指向dist/index.js与dist/plugin.js。二、快速开始安装、注册与启用 spec 预过滤1. 安装npm install --save-dev cypress/grep或使用 yarnyarn add --dev cypress/grep版本前提当前仓库 npm/grep/package.json 的peerDependencies声明cypress 15.10.0。需要说明的是README 的 Requirements 一节所写的 Cypress 10.0.0 面向的是 v3/v4 时代而 v5/v6 之后包内已改用Cypress.expose()公共配置 APICypress.env()自 Cypress 15.10.0 起被弃用因此在当前仓库对应版本下建议以 15.10.0为准。2. 在 support 文件中注册必需在cypress/support/e2e.js或 TS 版e2e.ts中加入// cypress/support/e2e.js const { register: registerCypressGrep } require(cypress/grep) registerCypressGrep()ES Modules / TypeScript 写法// cypress/support/e2e.ts import { register as registerCypressGrep } from cypress/grep registerCypressGrep()仓库自身的集成样例即采用该方式npm/grep/cypress/support/e2e.ts 中import { register } from ../../src/index后调用register()。3. 在setupNodeEvents中挂载插件可选spec 预过滤需要在cypress.config.js/cypress.config.ts中加入// cypress.config.js const { defineConfig } require(cypress) module.exports defineConfig({ e2e: { setupNodeEvents(on, config) { const { plugin: cypressGrepPlugin } require(cypress/grep/plugin) cypressGrepPlugin(config) return config }, }, })TypeScript 写法// cypress.config.ts import { defineConfig } from cypress import { plugin as cypressGrepPlugin } from cypress/grep/plugin export default defineConfig({ e2e: { setupNodeEvents(on, config) { cypressGrepPlugin(config) return config }, }, })plugin的完整实现见 npm/grep/src/plugin.ts。注意它读取的是config.expose这是 v6 之后基于Cypress.expose()的公共配置通道若同时希望测试通过时对实际结果做断言比对可以模仿本仓库的 npm/grep/cypress.config.ts 在setupNodeEvents内注册task并挂after:run钩子。三、按测试标题过滤grep标题过滤基于大小写不敏感的包含匹配作用于完整拼接后的测试名describe 标题 test 标题。常见命令# 运行标题中包含 login 的测试 npx cypress run --expose greplogin # 标题中包含完整短语 user authentication npx cypress run --expose grepuser authentication # 多个标题模式使用分号分隔命中任意一个即运行OR 逻辑 npx cypress run --expose greplogin; logout; signup底层逻辑见 npm/grep/src/utils.ts 的parseFullTitleGrep按;拆分与shouldTestRunTitlestraight非否定标题组只需命中一个而inverted-前缀标题组则要求全部不命中二者以 AND 关系叠加。四、按标签过滤grepTags4.1 给测试打标签标签可挂在it测试或describe套件上作为第三参数options.tags传入// 单个标签 it(should login successfully, { tags: smoke }, () { // test code }) // 多个标签使用数组 it(should handle errors, { tags: [smoke, critical] }, () { // test code }) // 标签挂在 describe 套件上其下所有测试继承 describe(User Management, { tags: user }, () { it(should create user, () { // test code }) })在 npm/grep/src/index.ts 中包通过全局类型扩展声明了TestConfigOverrides.tags?: string | string[]、SuiteConfigOverrides.tags以及Cypress.grep(grep?, tags?, burn?)这正是 TS 中可以直接传tags选项的原因。标签继承的实现位于 npm/grep/src/register.tsregister()会用describeGrep/itGrep覆盖全局describe/it维护一个suiteStack。测试的完整待匹配名nameToGrep为「外层 describe 标题 自身标题」以空格拼接而待匹配标签tagsToGrep则把suiteStack上每层的 tags 打平后再接上测试自身的 tags因此嵌套 describe 与父套件的标签会被一并考虑。4.2 标签的布尔过滤语法运行标签过滤# 运行带 smoke 标签的测试 npx cypress run --expose grepTagssmoke # OR空格分隔smoke 或 critical 任一命中即可 npx cypress run --expose grepTagssmoke critical # AND 连接需同时具备 smoke 与 critical npx cypress run --expose grepTagssmokecritical # NOT- 前缀带 smoke 但不带 slow npx cypress run --expose grepTagssmoke-slow该语法在 npm/grep/AGENTS.md 中总结为一条核心规则空格分隔的标签之间是 OR连接的标签之间是 AND-前缀表示取反例如smoke-high意为 smoke AND NOT high。解析算法见 npm/grep/src/utils.ts 的parseTagsGrep与shouldTestRunTags输入先按空格/逗号拆成若干 OR 分组ORS每个分组内部再按拆成 AND 单元-x解析为{ tag: x, invert: true }特殊地--前缀如--regression表示显式全局否定它会被追加到每一个OR 分组中实现任何分组命中时都不得携带该标签匹配判定为至少一个 OR 分组中所有 AND 单元全部满足非 invert 的标签存在于测试标签集中、invert 的标签不存在该测试即命中。五、组合、取反与专项模式5.1 标题与标签叠加# 标题含 login 且带 smoke 标签 npx cypress run --expose greplogin,grepTagssmoke # 标题含 user 且带 critical 或 smokeOR npx cypress run --expose grepuser,grepTagscritical smoke5.2 反向/排除过滤# 标题不含 slow npx cypress run --expose grep-slow # 不带 slow 标签 npx cypress run --expose grepTags-slow # 复杂组合标题含 login 但不含 slow且带 smoke 但不带 regression npx cypress run --expose greplogin; -slow,grepTagssmoke-regression5.3 只运行完全未打标签的测试npx cypress run --expose grepUntaggedtrue对应shouldTestRun中的快捷分支当grepUntagged为真时只要测试没有任何标签即运行见 npm/grep/src/utils.ts。5.4 预过滤 spec 文件grepFilterSpecs默认情况下所有 spec 文件都会被 Cypress 加载再由运行时过滤逐条筛掉测试。对大型测试套件可在启动插件后开启 spec 级预过滤让不包含任何匹配测试的 spec 根本不被运行# 只运行标题包含 login 的 spec npx cypress run --expose greplogin,grepFilterSpecstrue # 只运行含 smoke 标签测试的 spec npx cypress run --expose grepTagssmoke,grepFilterSpecstrue其机制见 npm/grep/src/plugin.ts当config.expose.grepFilterSpecs为真时插件用globby.sync按specPattern并应用excludeSpecPattern收集 spec 文件再逐一readFileSync读取源码文本交给find-test-names静态提取套件名、测试名与测试标签无需启动浏览器最后用shouldTestRun判断该 spec 是否保留并改写config.specPattern。若静态分析结果显示没有 spec 疑似命中插件会打印提示并回退为运行全部 spec交由运行时过滤逐条筛选——这是因为动态拼装出的标题/标签无法被静态分析捕捉。5.5 完全剔除不匹配测试grepOmitFiltered默认行为下被过滤掉的测试会以it.skip形式标记为 pending跳过。若希望结果中完全不出现它们启用npx cypress run --expose greplogin,grepOmitFilteredtrue代码路径对应 npm/grep/src/register.ts 中itGrep的分支命中测试直接执行否则当omitFiltered为真时不注册任何测试否则调用_it.skip(name, options, callback)将其标记为跳过。5.6 测试燃烧burn重复执行将命中的测试重复执行 N 次用于发现偶发性flaky失败# 标题含 login 的测试重复 5 次 npx cypress run --expose greplogin,burn5 # 全部测试重复 10 次 npx cypress run --expose burn10注意 burn 值必须是正整数否则 npm/grep/src/register.ts 会抛出Invalid grep burn value。当burn 1时itGrep用Cypress._.times(grepBurn, ...)注册 N 条同名测试并自动将标题改写为{原标题}: burning {k} of {N}以便在报告中区分每一次重复。六、把过滤规则固化到配置与脚本6.1 在 cypress.config 中固定过滤expose 顶层配置// cypress.config.js import { defineConfig } from cypress import { plugin as cypressGrepPlugin } from cypress/grep/plugin export default defineConfig({ expose: { // 始终只跑标题含 viewport 的测试 grep: viewport, // 始终开启 spec 预过滤 grepFilterSpecs: true, // 始终剔除而非跳过不匹配测试 grepOmitFiltered: true, }, e2e: { setupNodeEvents(on, config) { cypressGrepPlugin(config) return config }, }, })需留意命令行--expose ab,cd这类形式与配置文件expose字段共享同一配置通道。插件读取时同时兼容连字符别名如grep-tags/grep-burn/grep-untagged/grep-omit-filtered见 npm/grep/src/plugin.ts。6.2 在 package.json scripts 中固化常用分组{ scripts: { cy:smoke: cypress run --expose grepTagssmoke, cy:critical: cypress run --expose grepTagscritical, cy:fast: cypress run --expose grepTagsfast, cy:burn: cypress run --expose grepTagssmoke,burn5 } }本仓库 npm/grep/package.json 即遵循此思路为每种过滤场景准备了独立脚本每个脚本通过PROJECT_NAME环境变量指向对应的期望结果文件做断言例如yarn grep # 标题子串过滤对应 grep-task.cy.ts yarn tags # 按标签 smoke 过滤 yarn burn # burn5 重复执行 yarn filter:specs # grepTest 2 grepFilterSpecstrue yarn omit:specs # grepTest 2 grepOmitFilteredtrue yarn inverted # grep-Test 2标题取反 yarn tags:and # smokehighAND yarn tags:and:not # smoke-highAND NOT yarn tags:or # regression highOR yarn untagged # grepUntaggedtrue # ... 更多场景见 package.json scripts七、运行时过滤DevTools 控制台 API在交互模式cypress open下可在浏览器控制台直接动态过滤并触发测试重启// 按标题过滤 Cypress.grep(login) // 按标签过滤 Cypress.grep(null, smoke critical) // 标题 标签同时过滤 Cypress.grep(login, smoke) // 清除过滤 Cypress.grep()该 API 定义于 npm/grep/src/index.ts 的Cypress.grep类型声明中实现见 npm/grep/src/register.tsregister()首次调用时定义Cypress.grep其内部通过Cypress.expose(grep, ...)、Cypress.expose(grepTags, ...)、Cypress.expose(grepBurn, ...)写入公共配置并清空旧的grep-tags/grep-burn/burn别名随后调用restartTests()用setTimeout在下一事件循环通过window.top.document.querySelector(.reporter .restart).click()模拟点击 runner 的 restart 按钮使测试重新执行。八、TypeScript 支持自 v5 起cypress/grep随包附带类型声明exports的types字段分别指向./dist/index.d.ts与./dist/plugin.d.ts见 npm/grep/package.jsontags选项会自动获得类型支持。若你的moduleResolution较旧可任选以下方式方式一文件顶部三斜线引用推荐// 在 spec 文件最顶部 /// reference typescypress/grep / it(should work, { tags: smoke }, () { // TypeScript 将识别 tags 属性 })方式二在 tsconfig.json 中声明 types{ compilerOptions: { types: [cypress, cypress/grep] } }方式三忽略类型错误// ts-ignore it(should work, { tags: smoke }, () { // test code })九、源码级原理剖析9.1 模块职责划分npm/grep/AGENTS.md 给出了清晰的架构划分对应源码文件如下文件运行环境职责npm/grep/src/index.ts浏览器主入口全局类型声明tags选项、Cypress.grep并导出register刻意不引入 plugin避免浏览器端加载 Node 侧依赖npm/grep/src/register.ts浏览器support 文件覆盖it/describe/context/specify维护套件栈实现标签继承实施运行时过滤、skip/omit 与 burnnpm/grep/src/plugin.tsNodesetupNodeEvents解析config.expose基于globbyfind-test-names做 spec 静态预过滤npm/grep/src/utils.ts双端共享纯函数工具标题/标签解析与匹配判定浏览器与 Node 双入口隔离的设计非常关键register覆盖的是浏览器运行时的it/describe而plugin运行在 Node 进程中。若在 support 中误引用 pluginrequire(cypress/grep/plugin)或旧版require(cypress/grep/src/plugin)Node 端依赖fs、globby、find-test-names将无法在浏览器中加载。本包还在 npm/grep/package.json 的nx.implicitDependencies中声明!cypress用以避免构建顺序上的循环依赖。9.2 运行时过滤的完整决策链以命令行--expose grepTest 2,grepTagssmokehigh为例support 中register()读取Cypress.expose(grep)、grepTags、grepBurn、grepUntagged等值含连字符别名无任何过滤需求时直接 returnparseGrep(grep, grepTags)生成{ title: TitleGrep[], tags: TagGrep[][] }结构全局it被替换为itGrep每个测试注册时将suiteStack中所有 describe 名与自身名拼成nameToGrep把各层 tags 与自身 tags 打平成tagsToGrepshouldTestRun(parsedGrep, nameToGrep, tagsToGrep, !!grepUntagged)综合标题与标签判定命中 → 执行burn 1时展开为多条burning k of N未命中 → 依grepOmitFiltered决定完全剔除或it.skip。重复注册是幂等的register()发现it.name itGrep时直接返回避免二次覆盖仓库中专门有 multiple-registrations.cy.ts 用例与yarn multiple-registrations脚本验证。同时itGrep会透传 Mocha 的.skip/.only/.retries/.each与 describe 的.skip/.only/.each保证既有 Mocha 语义不被破坏。十、调试手段包基于debug模块打印日志通道名均为cypress/grep。插件侧Node 终端DEBUGcypress/grep npx cypress run --expose greplogin可看到 specPattern 收集、每个 spec 提取出的套件/测试名、预过滤命中数量等。support 侧浏览器在 DevTools 控制台先执行localStorage.debug cypress/grep然后刷新并运行测试即可看到每个测试的should test ... with tags ... run? true/false判定日志npm/grep/src/register.ts 中debugInstance输出被绑定到console.info便于在浏览器可见。十一、注意事项与已知限制spec 加载时机未启用grepFilterSpecs时所有 spec 都会先被加载过滤只发生在测试注册阶段。反向过滤与预过滤互斥-tag/-title这类取反过滤不兼容grepFilterSpecs静态分析无法在不知道完整标签集的情况下安全地排除不含某标签的 spec。运行时不可修改不能在测试运行中途通过Cypress.expose()改变过滤条件Cypress.grep()是专门为此设计的运行时 API。云端录制展示被过滤为 pending 的测试仍可能以 pending 状态出现在 Cypress Cloud 的录制结果中。标签书写习惯把{ tags: smoke fast }写成单个字符串会产生一个名为smoke fast的标签而非两个多标签务必用数组[smoke, fast]。推荐统一使用前缀以增强可搜索性。十二、仓库内测试与文档体系单元测试过滤逻辑标题取反、tag AND/OR、--全局否定、burn 参数校验等由 npm/grep/test/unit.spec.tsvitest覆盖可运行yarn test。端到端回归npm/grep/cypress/e2e 下每个 fixture 对应一种过滤场景如 tags/test1.cy.ts、burn.cy.ts、nested-describe.cy.ts、inherits-tag.cy.ts 等。npm/grep/cypress.config.ts 通过PROJECT_NAME环境变量在after:run中把实际测试结果与 npm/grep/expected-json 下的期望 JSON 做深比较OVERWRITE_EXPECTED1可回写期望文件。变更记录版本迁移要点见 npm/grep/CHANGELOG.md。十三、版本迁移要点v5 → v6涉及 CLI 参数形式Cypress.env()自 Cypress 15.10.0 起弃用公共配置 API 改为Cypress.expose()。把命令行--env/-e改为--expose/-x# 旧写法 npx cypress run --env grepTagstag1 tag2 # 新写法 npx cypress run --expose grepTagstag1 tag2v4 → v5涉及导出签名support 文件中注册函数由默认导出改为具名导出// 旧写法 const registerCypressGrep require(cypress/grep) // 新写法 const { register: registerCypressGrep } require(cypress/grep)同时 plugin 的引入路径与形式变化// 旧写法 const cypressGrepPlugin require(cypress/grep/src/plugin) // 新写法 const { plugin: cypressGrepPlugin } require(cypress/grep/plugin)更早版本v3/v4 起要求 Cypress 10.0.0从 v1 到 v2 时标题过滤与标签过滤已分离旧式--env greptag1 tag2应改写为--env grepTagstag1 tag2。十四、推荐的团队工作流一种可落地的分级策略先跑冒烟集npx cypress run --expose grepTagssmoke冒烟通过后跑全量npx cypress run排查问题时按分组定位npx cypress run --expose grepuser management或npx cypress run --expose grepTagscritical对疑似偶发失败的用例用燃烧确认npx cypress run --expose grepTagssmoke,burn5性能方面大套件优先开启grepFilterSpecstrue用「标题 标签」组合缩小范围整套测试中保持标签命名一致可将前缀、数组式多标签作为团队约定写入规范。小结cypress/grep把标题子串 布尔标签 spec 预过滤 燃烧四种能力收敛为一套--expose参数协议与两个隔离的入口浏览器register与 Nodeplugin。理解其双入口架构、标签解析优先级OR AND NOT与静态预过滤回退机制后你便能在 CI、本地与交互调试中灵活裁剪 Cypress 的执行范围让大规模 E2E 套件的按需运行变得可控而高效。【免费下载链接】cypressFast, easy and reliable testing for anything that runs in a browser.项目地址: https://gitcode.com/GitHub_Trending/cy/cypress创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表