关于 unit-tests
面向 bklit-ui 的测试技能,指导何时以及如何添加单元测试。它优先覆盖纯逻辑和用户可见回归,避免为了覆盖率编写脆弱或低信号的测试。
主要功能
- 01判断何时添加或跳过测试
- 02使用 Node 内置测试运行器与 tsx
- 03测试文件位置和断言模式
- 04配置包级及 Turbo 测试
- 05聚焦测试决策清单
适用场景
- 01评估代码改动是否需要测试
- 02为纯函数添加回归测试
- 03为新包配置测试
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ bklit/ bklit-ui --skill unit-tests安装后在 Claude Code 中输入/unit-tests确认已加载。
详细介绍
单元测试(bklit-ui)
在提出或编写测试前,请先阅读本技能。默认原则:测试更少,信号更强。
何时添加测试
当测试能锁定那些容易悄无声息地被破坏的行为时,添加测试:
| 值得测试 | 原因 |
|---|---|
| 纯函数/模块 | 输入稳定 → 输出稳定;运行快速;不涉及 DOM |
| 格式化器、解析器、比例计算、边界 | 字符串/数字输出回归会直接影响用户 |
| 代码生成/导出/注册表辅助函数 | 输出结构就是契约 |
| 不明显的边缘情况 | 空数据、反向范围、钳制 |
本仓库中的示例: chart-formatters.test.ts、highlight-segment-bounds.test.ts、animation.test.ts、apps/web/lib/studio/__tests__/*。
何时不要添加测试(除非用户明确要求)
不要只是为了提高覆盖率或“面面俱到”而添加测试:
| 跳过 | 原因 |
|---|---|
| React 组件渲染冒烟测试 | visx、motion、门户 → 容易脆弱;手动检查/文档检查成本更低 |
memo()/守卫提取(#65 风格) | 结构性性能重构;输出不变;RTL 挂载断言开销很大 |
| 默认属性透传 | formatValue = intFmt——类型检查 + 格式化器测试已覆盖 |
| 第三方库行为 | 不要重复测试 d3、visx 或 React |
| 简单 getter/单行包装器 | 无法提供回归信号 |
| 整张图表 SVG/JSX 快照 | 变动频繁,信号弱 |
如果用户问“要不要测试 X?”,当 X 属于此表时,回答不需要,并建议更轻量的替代方案(纯辅助函数测试、手动检查、CI 构建)。
仓库约定
测试运行器: Node 内置测试运行器 + tsx(除非仓库之后采用 Jest/Vitest)。
pnpm test # root — turbo runs packages with a test script
pnpm --filter @bklitui/ui test
cd apps/web && pnpm test
测试文件位置: 与被测代码相邻的 **/__tests__/**/*.test.ts。
模式:
import assert from "node:assert/strict";
import { describe, it } from "node:test";
import { myFn } from "../my-module";
describe("myFn", () => {
it("handles empty input", () => {
assert.equal(myFn([]), expected);
});
});
等价性测试(格式化器的首选):断言共享模块的输出与此前内联调用一致(例如使用相同区域设置/选项的 toLocaleDateString),使测试不受时区影响,并证明没有视觉回归。
新增软件包测试脚本: 添加到 package.json:
"test": "node scripts/run-tests.mjs"
使用精简的 scripts/run-tests.mjs 从 __tests__ 收集 *.test.ts,并调用 node --import tsx --test——Shell glob 在 Linux CI 中会失效。如果缺少 tsx,将其添加为开发依赖项。在根目录的 turbo.json 中接入 test 任务;CI 会运行 pnpm test。
决策清单(编写前执行)
- 逻辑是纯逻辑,或可提取为纯函数吗?→ 测试它。考虑先进行提取。
- 测试会因真实且用户可见的错误而失败吗?→ 值得考虑。
- 是否需要 jsdom/RTL/Playwright?→ 停下;向用户说明理由,或推迟到手动/视觉检查。
- 用户要求测试了吗?→ 仍然遵循本技能;不要做超出要求的事。
- 需要多少用例?→ 3–10 个有针对性的用例,不要穷举所有组合。
告知用户的内容
推荐测试时,请明确说明:
- 添加:“测试
chart-formatters.ts——它是纯逻辑,回归价值高。” - 跳过:“跳过 memo 拆分的组件测试——输出没有变化;构建 + 手动检查图表文档就足够了。”
- **CI:**添加或修改测试时,在 PR 测试计划中提及
pnpm test。
反模式
- 未经团队认可,为一次性需求引入 Jest/Vitest/Testing Library
- 模拟整个图表上下文来断言
useMemo调用次数 - 测试实现细节(Hook 顺序、内部组件名称)
- 重复类型检查器的工作(
expect(typeof x).toBe('function')) - 提交只能在本地通过的测试,因为其中硬编码了时区/区域设置字符串