33-js-concepts 项目如何用 Vitest 为文档代码示例编写测试并运行
2026/9/10 16:48:22 网站建设 项目流程

33-js-concepts 项目如何用 Vitest 为文档代码示例编写测试并运行

【免费下载链接】33-js-concepts📜 33 JavaScript concepts every developer should know.项目地址: https://gitcode.com/GitHub_Trending/33/33-js-concepts

33-js-concepts 项目把 33 个 JavaScript 概念文档里的代码示例当成可执行代码来对待:每个概念文档中的console.log示例,都要在tests/目录里有一份对应的断言测试来验证其行为。本文基于项目的 CONTRIBUTING.md、vitest.config.js 和 package.json,说明如何按项目的规范为文档代码示例编写 Vitest 测试,以及如何运行、观察这些测试。

测试体系的配置依据

在动手写测试之前,先弄清项目里两个关键文件决定了测试的运行规则。

vitest.config.js 的完整配置如下:

import { defineConfig } from 'vitest/config' export default defineConfig({ test: { include: ['tests/**/*.test.js'], globals: false, environment: 'node' } })

这三项配置直接约束了测试文件的写法:

  • include: ['tests/**/*.test.js']:只有tests/目录下匹配*.test.js的文件会被执行,新测试必须放在这个位置才会被收集;
  • globals: falsedescribeitexpect不会自动注入全局作用域,每个测试文件必须显式导入,否则测试根本无法运行;
  • environment: 'node':测试默认在 Node.js 环境运行,documentwindow等浏览器对象不可用——这决定了 DOM 相关的文档示例需要特殊处理(见下文)。

依赖方面,package.json 在devDependencies中声明了三个包:

"devDependencies": { "@vitest/coverage-v8": "^4.0.16", "jsdom": "^27.4.0", "vitest": "^4.0.16" }

vitest是测试运行器,jsdom用于个别需要 DOM 环境的测试,@vitest/coverage-v8提供覆盖率报告能力。首次拿到仓库后先运行npm install安装这些开发依赖,再执行测试命令。

测试的目录结构与命名规则

CONTRIBUTING.md 规定测试按概念(concept)组织,每个概念的测试放在以概念名命名的子目录中:

tests/ ├── call-stack/ │ └── call-stack.test.js ├── primitive-types/ │ └── primitive-types.test.js └── ...

新增一个概念文档的代码示例时,按同样的规则创建tests/{concept-name}/{concept-name}.test.js。当前仓库中实际的结构比示例更深一层,例如tests/fundamentals/call-stack/tests/async-javascript/callbacks/tests/advanced-topics/error-handling/,均遵循“按概念分组 +{concept-name}.test.js命名”的约定。

编写测试:把 console.log 示例转成断言

CONTRIBUTING.md 给出的核心规则是:文档里用console.log展示输出,测试里就必须用expect断言同一个输出。以 docs/concepts/primitive-types.mdx 开头的示例为例,文档中是:

const str = "hello"; console.log(typeof str); // "string"

对应的测试写法就是把预期输出写成断言:

import { describe, it, expect } from 'vitest' describe('Primitive Types', () => { it('should return string type', () => { expect(typeof "hello").toBe("string") }) })

第一行的显式导入是强制要求,对应globals: false的配置。一个完整的测试文件可以参考 tests/fundamentals/call-stack/call-stack.test.js:它把文档中“嵌套函数调用”的示例代码原样搬进it块,最后用expect(printSquare(4)).toBe(16)验证示例声称的输出。

错误路径用 toThrow 断言

文档中“这个操作会抛出错误”的示例,不能用普通断言覆盖,CONTRIBUTING.md 要求使用expect(() => { ... }).toThrow()。项目中实际用法见 tests/advanced-topics/data-structures/data-structures.test.js:

const weakMap = new WeakMap() // Cannot use primitives as keys expect(() => weakMap.set('string', 'value')).toThrow(TypeError)

这里验证的正是文档里“WeakMap 的 key 必须是对象”这一行为说明。

浏览器示例:跳过或切换到 jsdom

由于environment: 'node',涉及documentwindow的文档示例默认无法测试,CONTRIBUTING.md 的规则是跳过这类示例(对应测试文件里保留纯 Node 可执行的.test.js,不写 DOM 部分)。如果确实需要为 DOM 示例写测试,项目内的做法是创建单独的.dom.test.js文件,并用 Vitest 的注释 pragma 把该文件切到 jsdom 环境。例如 tests/async-javascript/callbacks/callbacks.dom.test.js 的文件头:

/** * @vitest-environment jsdom */ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'

该文件在beforeEach里用document.createElement('button')构建 DOM 节点,再用button.click()模拟事件,验证文档中事件回调示例的输出。注意文件名必须仍然匹配*.test.js.dom.test.js满足),否则不会被include规则收集。

严格模式的行为差异

CONTRIBUTING.md 特别提醒:Vitest 以严格模式运行测试,因此在非严格模式下“静默失败”的操作(比如给只读属性赋值),在测试中会抛出TypeError。写测试时如果某个示例在浏览器控制台里不报错、但测试里抛错了,先按这条规则判断,而不是怀疑文档示例写错。

运行测试并验证结果

package.json 的scripts提供了三个入口:

# 一次性运行全部测试 npm test # watch 模式,文件变化后自动重跑 npm run test:watch # 运行测试并生成覆盖率报告 npm run test:coverage

它们分别对应vitest runvitestvitest run --coverage。日常验证用npm test即可:它会执行tests/下所有匹配*.test.js的文件,任何一个断言与实际行为不符都会让对应测试失败,失败信息中能看到具体是哪个describe/it块、哪一行expect不成立——据此回到对应概念文档核对示例代码。修改测试文件本身时,npm run test:watch免去重复敲命令;npm run test:coverage则用于查看哪些文档示例的行为被测试覆盖到。

写作测试时的检查清单

按 CONTRIBUTING.md 的规则,新写一个测试文件前确认四件事:

  1. 文件位于tests/{concept-name}/下且命名为{concept-name}.test.js,能被tests/**/*.test.js匹配;
  2. 第一行显式import { describe, it, expect } from 'vitest'
  3. 文档示例的每个预期输出都转成了expect断言,错误路径用toThrow()
  4. 涉及 DOM/window 的示例要么不写,要么放进带@vitest-environment jsdompragma 的.dom.test.js文件。

全部满足后运行npm test,全部通过即说明这批文档代码示例的行为与文档描述一致。

【免费下载链接】33-js-concepts📜 33 JavaScript concepts every developer should know.项目地址: https://gitcode.com/GitHub_Trending/33/33-js-concepts

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询