找回密码
 立即注册
首页 业界区 安全 Svelte 最新中文文档教程(19)—— 测试

Svelte 最新中文文档教程(19)—— 测试

暴灵珊 2025-6-1 21:50:52
前言

Svelte,一个语法简洁、入门容易,面向未来的前端框架。从 Svelte 诞生之初,就备受开发者的喜爱,根据统计,从 2019 年到 2024 年,连续 6 年一直是开发者最感兴趣的前端框架 No.1
1.png

Svelte 以其独特的编译时优化机制著称,具有轻量级高性能易上手等特性,非常适合构建轻量级 Web 项目,也是我做个人项目的首选技术栈。
目前 Svelte 基于 Svelte 5 发布了最新的官方文档,但却缺少对应的中文文档。为了帮助大家学习 Svelte,为爱发电翻译了官方文档。
我同时搭建了 Svelte 最新的中文文档站点:https://svelte.yayujs.com ,如果需要辅助学习,也可以入手我的小册《Svelte 开发指南》,语法篇、实战篇、原理篇三大篇章带你系统掌握 Svelte!
虽说是翻译,但个人并不喜欢严格遵守原文,为了保证中文阅读流畅,会删减部分语句,对难懂的部分也会另做补充解释,希望能给大家带来一个好的中文学习体验。
欢迎围观我的“网页版朋友圈”、加入“冴羽·成长陪伴社群”,踏上“前端大佬成长之路”。
测试

测试可以帮助您编写和维护代码,防止出现回归问题。测试框架可以帮助您完成这一目标,通过让您能够描述对代码行为的断言或期望。
Svelte 对于您使用哪种测试框架并不持有特定立场 — 您可以使用 Vitest、Jasmine、Cypress 和 Playwright 等解决方案来编写单元测试、集成测试和端到端测试。
使用 Vitest 进行单元和集成测试

单元测试允许您测试代码中的小型独立部分。集成测试允许您测试应用程序的各个部分,以查看它们是否协同工作。如果您使用 Vite(包括通过 SvelteKit),我们推荐使用 Vitest。
首先安装 Vitest:
  1. npm install -D vitest
复制代码
然后调整您的 vite.config.js:
  1. /// file: vite.config.js
  2. import { defineConfig } from +++'vitest/config'+++;
  3. export default defineConfig({
  4.   // ...
  5.   // 告诉 Vitest 使用 `package.json` 文件中的 `browser` 入口点,即使它在 Node 中运行
  6.   resolve: process.env.VITEST
  7.     ? {
  8.         conditions: ['browser']
  9.       }
  10.     : undefined
  11. });
复制代码
[!NOTE] 如果加载所有包的浏览器版本不适合您的需求,例如您还需要测试后端库,您可能需要使用别名配置
现在您可以为 .js/.ts 文件中的代码编写单元测试:
  1. /// file: multiplier.svelte.test.js
  2. import { flushSync } from 'svelte';
  3. import { expect, test } from 'vitest';
  4. import { multiplier } from './multiplier.js';
  5. test('Multiplier', () => {
  6.         let double = multiplier(0, 2);
  7.         expect(double.value).toEqual(0);
  8.         double.set(5);
  9.         expect(double.value).toEqual(10);
  10. });
复制代码
在测试文件中使用符文(runes)

您可以在测试文件中使用符文。首先确保您的打包工具知道在运行测试之前要通过 Svelte 编译器处理文件,方法是在文件名中添加 .svelte(例如 multiplier.svelte.test.js)。之后,您就可以在测试中使用符文了。
  1. /// file: multiplier.svelte.test.js
  2. import { flushSync } from 'svelte';
  3. import { expect, test } from 'vitest';
  4. import { multiplier } from './multiplier.svelte.js';
  5. test('Multiplier', () => {
  6.         let count = $state(0);
  7.         let double = multiplier(() => count, 2);
  8.         expect(double.value).toEqual(0);
  9.         count = 5;
  10.         expect(double.value).toEqual(10);
  11. });
复制代码
如果被测试的代码使用了 effects,您需要将测试包装在 $effect.root 中:
  1. /// file: logger.svelte.test.js
  2. import { flushSync } from 'svelte';
  3. import { expect, test } from 'vitest';
  4. import { logger } from './logger.svelte.js';
  5. test('Effect', () => {
  6.         const cleanup = $effect.root(() => {
  7.                 let count = $state(0);
  8.                 // logger 使用 $effect 来记录其输入的更新
  9.                 let log = logger(() => count);
  10.                 // 效果通常在微任务后运行,
  11.                 // 使用 flushSync 同步执行所有待处理的效果
  12.                 flushSync();
  13.                 expect(log.value).toEqual([0]);
  14.                 count = 1;
  15.                 flushSync();
  16.                 expect(log.value).toEqual([0, 1]);
  17.         });
  18.         cleanup();
  19. });
复制代码
组件测试

您可以使用 Vitest 在隔离环境下测试您的组件。
[!NOTE] 在编写组件测试之前,请考虑是否真的需要测试组件本身,还是更多地关注组件内部的逻辑。如果是后者,考虑将逻辑提取出来单独测试,避免组件测试的开销
首先安装 jsdom(一个提供 DOM API 模拟的库):
  1. npm install -D jsdom
复制代码
然后调整您的 vite.config.js:
  1. /// file: vite.config.js
  2. import { defineConfig } from 'vitest/config';
  3. export default defineConfig({
  4.         plugins: [
  5.                 /* ... */
  6.         ],
  7.         test: {
  8.                 // 如果您在客户端测试组件,您需要设置 DOM 环境。
  9.                 // 如果不是所有文件都需要这个环境,您可以在测试文件顶部使用
  10.                 // `// @vitest-environment jsdom` 注释来代替。
  11.                 environment: 'jsdom'
  12.         },
  13.         // 告诉 Vitest 使用 `package.json` 文件中的 `browser` 入口点,即使它在 Node 中运行
  14.         resolve: process.env.VITEST
  15.                 ? {
  16.                                 conditions: ['browser']
  17.                         }
  18.                 : undefined
  19. });
复制代码
之后,您可以创建一个测试文件,在其中导入要测试的组件,以编程方式与之交互并编写关于结果的预期:
  1. /// file: component.test.js
  2. import { flushSync, mount, unmount } from 'svelte';
  3. import { expect, test } from 'vitest';
  4. import Component from './Component.svelte';
  5. test('Component', () => {
  6.         // 使用 Svelte 的 `mount` API 实例化组件
  7.         const component = mount(Component, {
  8.                 target: document.body, // 由于 jsdom 的存在,`document` 是可用的
  9.                 props: { initial: 0 }
  10.         });
  11.         expect(document.body.innerHTML).toBe('<button>0</button>');
  12.         // 点击按钮,然后刷新更改,这样您就可以同步地编写期望
  13.         document.body.querySelector('button').click();
  14.         flushSync();
  15.         expect(document.body.innerHTML).toBe('<button>1</button>');
  16.         // 从 DOM 中移除组件
  17.         unmount(component);
  18. });
复制代码
虽然这个过程非常简单明了,但它也比较底层且有些脆弱,因为组件的精确结构可能会频繁变化。像 @testing-library/svelte 这样的工具可以帮助简化测试。上面的测试可以重写为:
  1. /// file: component.test.js
  2. import { render, screen } from '@testing-library/svelte';
  3. import userEvent from '@testing-library/user-event';
  4. import { expect, test } from 'vitest';
  5. import Component from './Component.svelte';
  6. test('Component', async () => {
  7.         const user = userEvent.setup();
  8.         render(Component);
  9.         const button = screen.getByRole('button');
  10.         expect(button).toHaveTextContent(0);
  11.         await user.click(button);
  12.         expect(button).toHaveTextContent(1);
  13. });
复制代码
当编写涉及双向绑定、上下文或代码片段属性的组件测试时,最好为您的特定测试创建一个包装组件并与之交互。@testing-library/svelte 包含一些示例。
使用 Playwright 进行端到端测试

E2E(端到端的简称)测试允许您从用户的视角测试整个应用程序。本节以 Playwright 为例,但您也可以使用其他解决方案,如 Cypress 或 NightwatchJS。
要开始使用 Playwright,可以通过 VS Code 扩展 安装,或者使用 npm init playwright 从命令行安装。它也是运行 npx sv create 时设置 CLI 的一部分。
完成后,您应该有一个 tests 文件夹和一个 Playwright 配置。您可能需要调整该配置,告诉 Playwright 在运行测试之前要做什么 - 主要是在某个端口启动您的应用程序:
  1. /// file: playwright.config.js
  2. const config = {
  3.         webServer: {
  4.                 command: 'npm run build && npm run preview',
  5.                 port: 4173
  6.         },
  7.         testDir: 'tests',
  8.         testMatch: /(.+\.)?(test|spec)\.[jt]s/
  9. };
  10. export default config;
复制代码
现在您可以开始编写测试了。这些测试完全不知道 Svelte 作为一个框架的存在,所以您主要是和 DOM 交互并编写断言。
  1. // @errors: 2307 7031
  2. /// file: tests/hello-world.spec.js
  3. import { expect, test } from '@playwright/test';
  4. test('主页包含预期的 h1', async ({ page }) => {
  5.         await page.goto('/');
  6.         await expect(page.locator('h1')).toBeVisible();
  7. });
复制代码
Svelte 中文文档

本篇已收录在专栏 《Svelte 中文文档》,该系列预计 40 篇。
系统学习 Svelte,欢迎入手小册《Svelte 开发指南》。语法篇、实战篇、原理篇三大篇章带你系统掌握 Svelte!
此外我还写过 JavaScript 系列、TypeScript 系列、React 系列、Next.js 系列、冴羽答读者问等 14 个系列文章, 全系列文章目录:https://github.com/mqyqingfeng/Blog
欢迎围观我的“网页版朋友圈”、加入“冴羽·成长陪伴社群”,踏上“前端大佬成长之路”。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册