JairusSW/as-test

GitHub: JairusSW/as-test

一个运行时无关的 AssemblyScript 测试框架,提供模拟、快照、覆盖率与模糊测试,解决多运行时一致测试难题。

Stars: 8 | Forks: 0

╔═╗ ╔═╗    ╔═╗ ╔═╗ ╔═╗ ╔═╗

╠═╣ ╚═╗ ══  ║  ╠═  ╚═╗  ║ 

╩ ╩ ╚═╝     ╩  ╚═╝ ╚═╝  ╩ 

目录 - [为什么选择 as-test](#why-as-test) - [安装](#installation) - [文档](#docs) - [项目结构](#project-layout) - [编写测试](#writing-tests) - [Mocking](#mocking) - [快照](#snapshots) - [模糊测试](#fuzzing) - [运行时](#runtimes) - [示例](#examples) - [许可证](#license)
## 为什么选择 as-test 大多数 AssemblyScript 测试工具都与单一运行时绑定,通常是 Node.js。这在开发中可行,但无法反映代码在生产环境中的运行方式。 如果部署到 WASI、Wazero 或自定义运行时,你常常需要模拟所有内容,并为测试维护并行逻辑。 as-test 通过让你在实际目标运行时运行测试,同时仅模拟必要部分,解决了这一问题。 主要优势 - 运行时无关:可在 WASI、绑定或自定义运行器上测试 - 最小化模拟:尽可能使用真实导入 - 生产环境级测试:尽早捕获运行时特定问题 - 内联模拟和快照 - 自定义报告器和覆盖率 - 内置模糊测试支持 ## 安装 最简单的启动方式是使用项目初始化器: ``` npx as-test init ``` 这将生成一个基础配置文件、一个示例测试,以及可选的示例模糊测试器。 如果已有项目,只想安装包: ``` npm install --save-dev as-test ``` ## 文档 完整文档位于: ## 项目结构 默认情况下,`as-test` 会查找: - 测试文件位于 `assembly/__tests__` - 模糊测试器位于 `assembly/__fuzz__` - 配置文件为 `as-test.config.json` 生成的文件会存放在 `.as-test/` 目录中。 最小的 `as-test.config.json` 配置: ``` { "input": ["assembly/__tests__/*.spec.ts"], "output": ".as-test/", "buildOptions": { "target": "wasi" }, "runOptions": { "runtime": { "cmd": "node .as-test/runners/default.wasi.js " } } } ``` 覆盖率点过滤可配置,以便忽略已知噪声间隙: ``` { "coverage": { "enabled": true, "include": ["assembly/src/**/*.ts"], "ignore": { "labels": ["Call"], "names": ["panic", "serialize"], "locations": ["assembly/src/fuzz.ts:38:*"], "snippets": ["*message: string*"] } } } ``` ## 编写测试 测试通常位于 `assembly/__tests__/*.spec.ts`。 示例: ``` import { describe, expect, test } from "as-test"; describe("math", () => { test("adds numbers", () => { expect(1 + 2).toBe(3); }); }); ``` 运行全部测试: ``` npx ast test ``` 通过自动工作池运行: ``` npx ast test --parallel ``` 运行单个匹配文件: ``` npx ast test math ``` 你无需学习所有 CLI 标志即可开始。大多数项目可以从 `npx ast test` 起步,仅在需要时添加更多配置。 ## 模拟 支持模拟,但理念是谨慎使用。 使用 `as-test`,理想路径是针对真实运行时和真实导入运行代码。当这不切实际时,可以模拟单个导入,而不是围绕假行为重建整个环境。 对于本地函数,使用 `mockFn` 和 `unmockFn`。对于主机导入,使用 `mockImport` 和 `unmockImport`。 这在以下场景特别有用: - 导入与外部世界通信 - 主机函数难以在测试中重现 - 你希望强制触发难以自然重现的边缘情况 这能让测试保持专注。你仍可在不使每个测试依赖真实运行时的情况下验证 AssemblyScript 逻辑。它也与快照配合良好,当你希望捕获模拟导入的输出并确保其随时间保持稳定时。 示例: ``` import { describe, expect, mockFn, test, unmockFn } from "as-test"; function getConfig(): string { return "name=prod\nmode=live"; } mockFn(getConfig, (): string => "name=demo\nmode=test"); describe("config", () => { test("reads mocked data", () => { expect(getConfig()).toContain("demo"); }); }); unmockFn(getConfig); ``` 对于导入模拟,思路相同,但通常更简单的方式是将导入函数保留在一个小型包装模块中,并模拟该导入路径。 ## 快照 当输出比精确步骤断言更重要时,快照非常有用。 它们适用于: - 生成的字符串或结构化文本 - 序列化值 - 模拟导入的输出 - 较大的结果,逐字段检查会显得笨拙 这能让你在保持测试可读性的同时,锁住不应意外变化的行为。 示例: ``` import { describe, expect, test } from "as-test"; function renderReport(): string { return "name=demo\nmode=test"; } describe("report", () => { test("matches the saved output", () => { expect(renderReport()).toMatchSnapshot(); }); }); ``` 首次运行快照测试时,使用以下命令创建快照: ``` npx ast test --create-snapshots ``` 之后,普通的 `npx ast test` 会验证它。 如果现有快照确实发生变化,使用以下命令覆盖: ``` npx ast test --overwrite-snapshots ``` ## 模糊测试 模糊测试器通常位于 `assembly/__fuzz__/*.fuzz.ts`。 示例: ``` import { expect, FuzzSeed, fuzz } from "as-test"; fuzz("bounded integer addition", (left: i32, right: i32): bool => { const sum = left + right; expect(sum - right).toBe(left); return sum >= i32.MIN_VALUE; }).generate((seed: FuzzSeed, run: (left: i32, right: i32) => bool): void => { run(seed.i32({ min: -1000, max: 1000 }), seed.i32({ min: -1000, max: 1000 })); }); ``` 传递第三个参数以覆盖单个目标的运行次数,而不更改全局模糊测试配置: ``` fuzz("hot path stays stable", (): void => { expect(1 + 1).toBe(2); }, 250); ``` 或将其作为 `.generate(...)` 的第二个参数传递: ``` fuzz("ascii strings survive concatenation boundaries", (input: string): bool => { expect(input.length <= 40).toBe(true); return true; }).generate((seed: FuzzSeed, run: (input: string) => bool): void => { run(seed.string({ charset: "ascii", min: 0, max: 40 })); }, 250); ``` 你仍可通过 CLI 覆盖模糊运行,以强制当前命令使用不同的运行次数: ``` npx ast fuzz --runs 500 npx ast fuzz --runs 1.5x npx ast fuzz --runs +10% npx ast fuzz --runs +100000 ``` 如果在初始化时使用了模糊示例,`as-test.config.json` 中已有相关配置。否则,添加一个 `fuzz` 块,以便 `npx ast fuzz` 知道要构建什么: ``` { "fuzz": { "input": ["./assembly/__fuzz__/*.fuzz.ts"], "target": "bindings" } } ``` `ast fuzz` 会跨选定模式运行模糊文件,对每个文件报告一个结果,并保持最终汇总与普通测试分开。如果希望使用单个组合命令,请使用 `ast test --fuzz`。 当模糊测试失败时,`as-test` 会打印确切的失败种子及一次运行重现命令,例如 `ast fuzz ... --seed --runs 1`。崩溃记录在 `.as-test/crashes` 中,也包含传递给 `run(...)` 的输入,这有助于调试生成器本身的副作用。 仅运行模糊测试: ``` npx ast fuzz ``` 同时运行测试和模糊测试: ``` npx ast test --fuzz ``` 模糊测试在需要更广泛输入覆盖时可用,但不会干扰正常的测试流程。你可以从普通规格开始,稍后再添加模糊测试。 ## 运行时 使用 `as-test` 的主要原因之一是你不必锁定到单一运行时。 如果项目运行在 WASI、绑定或自定义运行时下,你可以将测试指向该环境,而不是将 Node.js 视为唯一执行方式。 例如,`as-test.config.json` 中一个简单的 WASI 配置可能如下: ``` { "input": ["./assembly/__tests__/*.spec.ts"], "buildOptions": { "target": "wasi" }, "runOptions": { "runtime": { "cmd": "node ./.as-test/runners/default.wasi.js " } } } ``` 然后正常运行测试: ``` npx ast test ``` 如果希望保留多个运行时,可使用模式: ``` { "input": ["./assembly/__tests__/*.spec.ts"], "modes": { "wasi": { "buildOptions": { "target": "wasi" }, "runOptions": { "runtime": { "cmd": "node ./.as-test/runners/default.wasi.js " } } }, "bindings": { "buildOptions": { "target": "bindings" }, "runOptions": { "runtime": { "cmd": "node ./.as-test/runners/default.bindings.js " } } } } } ``` 运行特定模式: ``` npx ast test --mode wasi ``` 或 ``` npx ast test --mode wasi,bindings ``` 这是整个项目的核心理念:编写一次测试,然后选择与实际运行代码匹配的运行时。 ## 示例 可运行的示例项目位于 [examples/](./examples/README.md)。它们适用于希望查看完整配置而非孤立代码片段的场景。 ## 许可证 该项目采用开源许可证分发。开发出于热情,但如果你希望经济支持,可以向项目的 [GitHub Sponsors](https://github.com/sponsors/JairusSW) 页面捐款。 你可以通过以下链接查看完整许可证:[许可证](./LICENSE) ## 联系 请将所有问题提交至 [GitHub Issues](https://github.com/JairusSW/json-as/issues),如需交流,请发送邮件至 [me@jairus.dev](mailto:me@jairus.dev) - **邮箱:** 发送咨询、问题或请求至 [me@jairus.dev](mailto:me@jairus.dev) - **GitHub:** 访问官方仓库 [此处](https://github.com/JairusSW/json-as) - **网站:** 访问我的官方网站 [jairus.dev](https://jairus.dev/) - **Discord:** 联系我:[我的 Discord](https://discord.com/users/600700584038760448) 或 AssemblyScript Discord 服务器 [此处](https://discord.gg/assemblyscript/)
标签:AssemblyScript, GNU通用公共许可证, MITM代理, Mocking, Node.js, npm, npx, SEO: AssemblyScript 测试, SEO: as-test, WASI, Wazero, WebAssembly, 代码覆盖率, 前端测试, 功能: 最小化 Mock, 功能: 生产级测试, 单元测试, 并行逻辑, 快照测试, 技术栈: TypeScript, 搜索词: WASI 测试框架, 搜索词: 运行时无关测试, 测试框架, 生产环境测试, 自定义报告器, 自定义脚本, 运行时无关, 集成初始化