尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Langflow 前端测试生成清单:从 Jest 配置到对抗性测试的完整质量准则

Langflow 前端测试生成清单:从 Jest 配置到对抗性测试的完整质量准则 Langflow 前端测试生成清单从 Jest 配置到对抗性测试的完整质量准则【免费下载链接】langflowLangflow is a powerful tool for building and deploying AI-powered agents and workflows.项目地址: https://gitcode.com/GitHub_Trending/la/langflow本文以 Langflow 仓库中frontend-testing技能自带的提交前验证清单checklist为核心逐项拆解前端测试的编写规范从写测试前的源码通读、文件结构约定、RTL 查询优先级到强制要求的对抗性测试、覆盖率门槛与执行验证命令并结合 jest.config.js、jest.setup.js 等真实配置文件说明每条规则背后的工程依据。读完本文你可以按照 Langflow 的实际标准提交一份结构合规、覆盖充分、可独立运行的前端测试。清单的定位与适用前提原始清单位于 checklist.md其开篇即说明用途Verify each item before submitting test code for Langflow frontend.——它是提交前逐条核对的验证清单而非泛泛的最佳实践合集。它隶属于 SKILL.md 所定义的前端测试技能适用于 React 组件、hooks、工具函数与 Zustand store 的单元测试或集成测试编写、评审、覆盖率提升与 flaky 测试排查等场景。该清单所针对的技术栈在 SKILL.md 中有明确版本说明Jest 30.x、ts-jest、React Testing Library 16.x、testing-library/user-event 14.x、React 19.x、Zustand 4.x测试运行环境为 jsdom经 jest-environment-jsdom 30.x。理解这些版本前提是理解清单中诸多规则例如绝不用vi.*、必须await所有 userEvent 调用的原因。写测试之前Pre-Writing 阶段清单的第一节要求在动笔前完成六项准备本质是先读懂被测对象再决定测什么、mock 什么完整通读源文件再写任何测试识别所有导出函数、组件、hooks、类型——这是后续覆盖率 100% 函数覆盖要求的前提识别所有条件分支if/else、三元、switch、提前 return、/||短路求值——这些正是分支覆盖率 95% 需要覆盖的对象识别所有需要 mock 的依赖检查 jest.setup.js 中已有的全局 mock避免重复 mock检查是否存在可扩充的既有测试文件优先扩展而不是新建文件。最后两条在 Langflow 仓库中有非常具体的落点。jest.config.js 中同时配置了两个 setup 文件setupFilesAfterEnv: [rootDir/src/setupTests.ts], setupFiles: [rootDir/jest.setup.js],jest.setup.js 在每个测试文件加载前执行已全局 mock 了react-i18next返回en.json英文文案、支持{{param}}插值与Trans标签解析、radix-ui/react-form、react-markdown、remark-gfm、remark-math、rehype-mathjax/browser、/components/common/shadTooltipComponent、/stores/darkStore、lucide-react/dynamicIconImports等模块并补齐了import.meta.env、crypto、URL、TextEncoder/TextDecoder、localStorage/sessionStorage等 jsdom 缺失的全局对象setupTests.ts 注入testing-library/jest-dom与jest-axe的toHaveNoViolations并 mock 了ResizeObserver、IntersectionObserver和window.matchMedia。因此在测试文件中重复jest.mock(/stores/darkStore, ...)不仅多余还可能与全局 mock 的返回形状冲突——这正是清单中Does NOT re-mock modules already mocked injest.setup.js一条的来由。文件结构命名、路径与生命周期钩子清单的 File Structure 一节规定了测试文件的物理形态位置放在__tests__/目录或与被测源文件同目录co-located。Langflow 仓库两种模式并存例如 restore-dismissed-node.test.tsx 采用__tests__/子目录durationStore.test.ts 位于src/stores/__tests__/。这一约定由 jest.config.js 的testMatch精确支撑testMatch: [ rootDir/src/**/__tests__/**/*.{test,spec}.{ts,tsx}, rootDir/src/**/*.{test,spec}.{ts,tsx}, ],命名ComponentName.test.tsx或util-name.test.ts约定导入统一使用/路径别名——对应jest.config.js中^/(.*)$: rootDir/src/$1的moduleNameMapper配置jest.mock()调用放在文件顶部、import 之后beforeEach中包含jest.clearAllMocks()beforeEach重置 Zustand store 状态如果用到 storeafterEach清理 fake timers如果用了。一个值得注意的细节testPathIgnorePatterns中显式忽略了test-utils.tsxtestPathIgnorePatterns: [/node_modules/, test-utils.tsx],这意味着名为test-utils.tsx的文件虽形似测试但不会被执行——清单末节Final Review最后一条Test file is not intestPathIgnorePatterns(not namedtest-utils.tsx)正对应此配置提醒不要把测试逻辑写进会被 Jest 跳过的文件名里。测试质量单行为、AAA 与测试隔离Test Quality 一节的核心规则可以概括为三点每个it()只测一个行为。清单给出的判据很实用测试名里如果出现 and就应该拆成两个测试测试名遵循should [behavior] when [condition]格式测试按从简单到复杂的顺序排列默认渲染 → props 变化 → 用户交互 → 异步 → 错误与边界使用 Arrange-Act-AssertAAA结构各阶段之间用空行分隔不测实现细节不查内部 state、不查 CSS class、不查私有函数测试间互不依赖任何测试不得依赖另一个测试的副作用。仓库中的 component-test.template.tsx 就是这些规则的样板化体现模板把测试分成rendering/user interactions/async behavior/edge cases/cleanup五个 describe 区块并在头部注释中要求复制后删除用不到的部分、替换所有TEMPLATE_*占位符。查询与断言RTL 查询优先级Queries and Assertions 一节规定了基于语义的查询方式优先级从高到低getByRole getByLabelText getByText getByTestId其余硬性规则断言元素不存在必须用queryBy*expect(queryByText(x)).not.toBeInTheDocument()getBy*找不到会直接抛错无法用于否定断言异步元素用findBy*或waitFor所有查询统一走screen对象不要从render()解构断言使用 jest-dom matchertoBeInTheDocument()、toHaveValue()、toBeDisabled()等这些由 setupTests.ts 中的import testing-library/jest-dom注入禁止用.innerHTML、.className、.style做断言——这是把测试与实现细节解耦的底线。由于 setupTests.ts 还通过expect.extend(toHaveNoViolations)接入了jest-axe对可访问性敏感的关键组件如仓库中已存在的 outputModal.a11y.test.tsx还可以用toHaveNoViolations()做无障碍断言这与按 role 查询的查询优先级一脉相承。用户交互userEvent 而非 fireEvent清单在 User Interactions 一节的要求非常具体必须用userEvent.setup()不用fireEvent——userEvent 会派发完整的键盘/鼠标事件序列如pointerdown→pointerup→click比fireEvent.click更贴近真实用户行为所有 userEvent 调用必须await与 fake timers 结合时必须写成userEvent.setup({ advanceTimers: jest.advanceTimersByTime })否则 userEvent 内部的时间推进与 Jest 假时钟会互相打架导致交互永远无法完成。仓库内 restore-dismissed-node.test.tsx、color-picker-buttons.test.tsx 等既有测试均遵循const user userEvent.setup()await user.click(...)的写法。Mocking只 mock 必要的东西Mocking 一节给出了 Langflow 的 mock 纪律规则说明只用 Jest APIjest.fn()、jest.mock()、jest.spyOn()绝不允许vi.*仓库用的是 Jest 30 而非 Vitest最小化 mock优先用真实实现只 mock 必要部分不 mock 基础 UI 组件/components/ui/下的组件一律真实渲染不重复 mock 全局 mock见 jest.setup.js 中已 mock 的模块清单mock 返回形状与真实 API 一致保持类型安全断言 mock 用jest.mocked()获得类型安全的 mock 断言关于mock 返回形状与真实 API 一致可以对照 component-test.template.tsx 中被注释掉的示例mock/controllers/API/api时提供get/post两个jest.fn()mock store 时返回一个接受 selector 的函数形状为selector ? selector({ nodes: [], edges: [] }) : {}与 Zustand 选择器调用方式完全一致。SKILL.md 中还有配套的量化警戒线Count mocks — if 3 deep, rethinkmock 层数超过 3 层就该重新审视测试设计。异步测试waitFor、act() 与 fake timersAsync 一节的五条规则覆盖了异步测试中最常见的坑每个waitFor回调内只放一个断言多个断言同时失败时会掩盖真正的根因所有 promise 正确await状态更新操作用act()包裹store 更新、定时器推进fake timers 在afterEach中清理顺序固定先jest.runOnlyPendingTimers()再jest.useRealTimers()——先跑完挂起计时器再切回真实时钟避免悬挂 timer 污染下一个测试文件不允许 unhandled promise rejection。仓库中 mutate-template.test.ts、use-response-complete-cue.test.ts 等测试均使用了jest.useFakeTimers()说明 fake timers 在该项目中是受支持的常规手段但必须配套完成上述清理。强制项对抗性测试Challenge Tests这是清单中用 MANDATORY 标注的章节也是信息密度最高的部分。核心观点是只测 happy path 的测试集是不合格的——正常路径测试只证明一切完美时代码能跑而真正的 bug 藏在裂缝里。必须主动写试图搞坏代码的测试意外输入null、undefined、、[]、{}、0、-1边界值最大长度、恰好达到上限、超出上限一个、零个元素、最大元素数畸形数据缺字段、多字段、类型错误如日期格式错误、数字以字符串形式出现错误状态API 500 / 404 / 401、网络失败、超时验证不应发生的事禁止的操作应被拒绝、错误用户无法访问资源验证错误信息本身不只断言它失败了还要断言如何失败——错误消息内容、错误类型是否正确基于需求/规格写测试而不是照抄源码逻辑——这是发现代码偏离预期行为的唯一方式。SKILL.md 在此之上还补充了仓库特有的例子验证删除某个 flow 不会误删其他用户的 flow、验证只读用户无法触发写操作、验证 XSS 负载被净化、双击提交按钮、异步操作进行中卸载组件等。并给出失败处置原则当测试失败时先怀疑代码写错了而不是悄悄修改断言迁就现状。覆盖率门槛与验证命令Coverage 一节给出硬性指标针对单个源文件指标门槛函数覆盖100%分支覆盖 95%行覆盖 95%同时要求所有导出函数/组件都被测试所有条件分支两侧都覆盖包括所有 catch 块。这些目标与 jest.config.js 的覆盖率配置相呼应coverageProvider: v8, collectCoverageFrom: [ src/**/*.{ts,tsx}, !src/**/*.{test,spec}.{ts,tsx}, !src/**/tests/**, !src/**/__tests__/**, !src/setupTests.ts, !src/vite-env.d.ts, !src/**/*.d.ts, ], coverageReporters: [text, lcov, html, json, json-summary],即默认对整个src/**收集覆盖、排除测试文件本身并输出 lcov/html/json 多种报告。验证单个文件覆盖率时按清单给出的命令执行npm test -- --coverage --collectCoverageFromsrc/path/to/source.ts path/to/test.test.ts执行验证与最终审查Execution 一节要求测试在四个层面都被验证过单文件无错误运行npm test -- path/to/file.test.tsx输出中无 console 警告或错误除非有意抑制隔离运行通过单跑该文件全量套件通过无跨文件污染覆盖率命令验证通过。这些命令与 package.json 中的 scripts 一一对应test: jest、test:coverage: jest --coverage、test:watch: jest --watch。值得注意的是 setupTests.ts 中默认会过滤两条特定警告ReactDOM.render is deprecated与componentWillReceiveProps has been renamed——清单中or they are intentionally suppressed的豁免正是指这类在全局 setup 中被有意识地抑制的警告除此之外任何新出现的 console 错误都应被视为测试缺陷。CI 环境下 jest.config.js 还会启用额外配置CI true时接入jest-junitreporter输出到test-results/junit.xml、限制maxWorkers: 50%并开启verbose。因此在 CI 上审查测试结果时可直接查看生成的 junit 报告。Final Review 一节是提交前的最后五项静态检查测试代码中没有遗留console.log没有.only或.skip没有超过 5000ms 的硬编码超时没有本可以正确类型化的any断言测试文件名不在testPathIgnorePatterns中即不要叫test-utils.tsx否则 Jest 会直接跳过它参见前文testPathIgnorePatterns配置。小结清单如何嵌入 Langflow 前端测试工作流把整份清单串起来它实际上定义了 Langflow 前端测试从生到死的完整生命周期写之前通读源码并对照 jest.setup.js 确定 mock 边界 → 按 jest.config.js 的testMatch约定放置与命名文件 → 以 AAA 结构、语义化查询和 userEvent 编写单行为测试 → 强制补充对抗性用例 → 用--coverage --collectCoverageFrom验证 100%/95%/95% 门槛 → 通过单文件、隔离、全量三层执行验证 → 用 Final Review 五项做静态终审。配套的 组件测试模板 提供了可直接复制起步的骨架而 SKILL.md 中的反模式表The Liar / The Mirror / The Giant 等七类则是本清单在评审阶段的人肉兜底。对维护者而言这份清单的价值在于它不是抽象教条每一条规则都能在仓库的 Jest 配置、全局 setup 或既有测试文件中找到对应的事实锚点。【免费下载链接】langflowLangflow is a powerful tool for building and deploying AI-powered agents and workflows.项目地址: https://gitcode.com/GitHub_Trending/la/langflow创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表