ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

NativeScript 仓库单元测试编写指南:基于 Vitest 与 Nx 的实践

NativeScript 仓库单元测试编写指南:基于 Vitest 与 Nx 的实践 【免费下载链接】NativeScript⚡ Write Native with TypeScript ✨ Best of all worlds (TypeScript, Swift, Objective C, Kotlin, Java, Dart). Use what you love ❤️ Angular, React, Solid, Svelte, Vue with: iOS (UIKit, SwiftUI), Android (View, Jetpack Compose), Flutter and you name it compatible.项目地址https://gitcode.com/gh_mirrors/na/NativeScript点击查看免费下载本指南基于 NativeScript 官方仓库中面向贡献者的单元测试规范文档.agent/skills/feat/references/WritingUnitTests.md编写系统讲解该仓库中*.spec.ts测试的组织方式、运行命令、编写规范与测试环境细节并结合packages/core等包的源码、配置文件与实际测试用例进行深度印证。读完本文你将掌握如何在该仓库中定位测试文件、使用 Nx 与 Vitest 跑通/过滤测试、编写同步与异步断言以及理解 Node 环境下平台全局变量桩stub机制与 e2e 测试的边界划分。一、测试的组织方式与被测源码同目录的*.spec.ts在 NativeScript 仓库中单元测试采用 Vitest 作为测试框架通过 Nx 按包package运行。测试文件是标准*.spec.ts与被测源码同目录存放colocated散布在整个 workspace 的各包中。例如packages/core/xml/index.spec.ts紧挨着被测源码packages/core/xml/index.tspackages/core/application/activity-lifecycle.android.spec.ts、packages/core/application/application-delegate.spec.ts、packages/core/application/scene-delegate-bridge.spec.ts、packages/core/application/window-content-resolver.spec.ts等对应packages/core/application/目录下的各模块。从packages/core/project.json的namedInputs配置可以看出production输入明确排除了**/*.spec.ts也就是说测试文件只服务于测试目标不参与包的正式构建产物——这是 Nx 缓存与依赖图task graph中对测试文件的标准处理方式。各包在project.json中通过 Nx 目标target暴露test任务例如packages/core/project.json中的test: { executor: nx/vitest:test, outputs: [{options.reportsDirectory}], options: { reportsDirectory: ../../coverage/packages/core } }即由nx/vitest:testexecutor 驱动覆盖报告输出到coverage/packages/core下。拥有test目标的包如core、vite各自在包根目录维护自己的 Vitest 配置packages/core/vite.config.tscore 包把 Vitest 配置放在vite.config.ts中packages/vite/vitest.config.tsvite 包使用独立的vitest.config.ts。二、运行测试Nx 命令、watch 模式与按名称过滤仓库的完整环境准备请参考 tools/notes/DevelopmentWorkflow.md克隆仓库后先执行npm run setup安装本地依赖之后既可以通过npm start打开交互菜单输入core.test过滤到nativescript.core.test任务后回车也可以直接使用 Nx 命令。运行 core 包的全部单元测试npx nx run core:test启用 watch 模式改动源码或测试后自动重跑npx nx run core:test --watch按describe/it的名称过滤测试例如只跑packages/core/xml/index.spec.ts中名为XmlParser的 describe 块npx nx run core:test -t XmlParser-t是 Vitest 的--testNamePattern别名也常与--watch组合使用npx nx run core:test --watch -t XmlParser在packages/core/vite.config.ts中可以看到 Vitest 的核心配置test块test: { watch: false, globals: true, environment: node, pool: forks, execArgv: process.env[VITEST_NO_OPT] ? [--max-opt0] : [], setupFiles: [vitest.setup.ts], include: [**/*.{test,spec}.{ts,mts}], reporters: [default], coverage: { reportsDirectory: ../../coverage/packages/core, provider: v8, }, },其中值得注意的几点globals: true意味着describe、it、expect、beforeEach、vi等全局可用详见下文第三节environment: node确认测试运行在 Node 环境而非真机include匹配*.test.ts与*.spec.ts含.mtspool: forks使用子进程池执行测试当设置了VITEST_NO_OPT1环境变量时会以--max-opt0参数启动 worker——配置注释说明这是为了模拟 iOS 上 V8 以 jitless 方式执行 JavaScript 的行为在基准测试benchmark中读数的差异非常明显setupFiles指向packages/core/vitest.setup.ts这是平台全局桩的关键入口覆盖率由 v8 provider 收集输出到coverage/packages/core。作为对比packages/vite/vitest.config.ts中globals: false因此 vite 包测试文件中必须显式从vitest导入 API而 core 包则无需显式导入但显式导入同样合法。三、编写测试标准 Vitest API 与同步断言使用标准 Vitest API 编写测试describe组织套件、it/test定义用例、expect做断言、beforeEach做前置准备、vi做 mock。由于 core 包配置了globals: true这些 API 在全局可用从vitest导入是可选的。原文档给出的最小示例Observable的once语义import { Observable } from .; describe(Observable, () { it(notifies a listener once, () { const observable new Observable(); let callCount 0; observable.once(test, () callCount); observable.notify({ eventName: test, object: observable }); observable.notify({ eventName: test, object: observable }); expect(callCount).toBe(1); }); });该示例对应packages/core/data/observable/index.ts中Observable的once/notify机制once注册的监听器在首次触发后即被移除因此连续两次notify后callCount仍为 1。再看仓库中真实的测试风格。packages/core/xml/index.spec.ts用describe组织Vanilla与Angular两种风味并通过beforeEach重建XmlParser实例保证每个用例互不污染describe(Vanilla, () { let last_element null; let last_attrs null; let last_data null; let parser null; beforeEach(() { parser new XmlParser(function (event) { switch (event.eventType) { case ParserEventType.StartElement: last_element event.elementName; last_attrs event.attributes; break; case ParserEventType.Text: last_data event.data; break; } }); }); it(handles whitespace around attribute , () { parser.parse(TextField text \n hello /); expect(last_element).toBe(TextField); expect(last_attrs[text]).toBe(hello); }); // ... });packages/core/utils/native-helper.ios.spec.ts则展示了beforeEach/afterEach配对保存与恢复全局状态、以as any构造轻量假对象fake的惯用做法——用createUIWindow/createNativeWindow工厂函数生成身份等价的桩对象避免依赖真实 UIKit 类型beforeEach(() { previousActiveWindow getActiveWindow(); previousiOSWindow getiOSWindow(); previousApplication global.UIApplication; setActiveWindow(undefined); setiOSWindow(undefined); }); afterEach(() { setActiveWindow(previousActiveWindow); setiOSWindow(previousiOSWindow); global.UIApplication previousApplication; });四、异步测试async 函数 await异步测试就是普通的async函数返回或await你的 Promise然后对结果做断言。Vitest 会自动等待返回的 Promise 结算超时默认 5 秒可通过it(name, fn, timeout)的第三参数调整则判失败。仓库中packages/core/utils/native-helper.ios.spec.ts、packages/core/application/application-delegate.spec.ts等文件均包含async () 形态的用例。写异步用例时避免空跑或遗漏await确保断言在 Promise resolve 之后执行。五、测试环境Node 下的平台全局桩与 e2e 边界单元测试运行在 Node 中而不是设备上。为了让 core 模块能够加载packages/core/vitest.setup.ts对 NativeScript 的平台全局变量做了桩替换平台标志位global.__UNIT_TEST__ true、global.__DEV__ true、global.__ANDROID__ false、global.__IOS__ true、global.__VISIONOS__ false、global.__APPLE__ true、global.__COMMONJS__ false以及global.__CSS_PARSER__ css-tree注释说明该值在真实应用中由打包器注入css-tree 解析器是默认值平台对象的最小可用桩global.NSObject、global.NSTimer、global.NSBundle、global.NSData、global.NSString、global.NSFileManager、global.UIScreen、global.UIDevice、global.UIApplication等其中NSData的桩会记录调用的 selector 与参数dataWithData、dataWithBytesLength等用于在规格测试中断言字节所有权ownership选择是否正确加密相关桩vi.stubGlobal(crypto, { randomUUID: ... })用于让 crypto polyfill 顺利通过同时提供 iOS 侧global.SecRandomCopyBytes/global.NSCCrypto与 Android 侧global.org.nativescript.winter_tc.Crypto两套桩注释说明这样可以在同一个规格测试中通过切换__ANDROID__/__IOS__来分别覆盖wgc/crypto的平台分支工具类桩global.interop、global.NativeClass、global.WeakRef.prototype.get等。需要强调的是这些桩只保证模块能被加载、纯逻辑可被验证真实的 iOS/Android API 并不存在。如果你的测试需要更多原生表面native surface应该扩展packages/core/vitest.setup.ts中的桩而不是依赖真机能力。依赖真实原生运行时行为的功能应该放到 e2e 测试套件中。仓库中的 e2e 应用包括apps/automated自动化 e2e 测试、apps/toolbox本地开发实验与用例确认更简单常用和apps/ui更复杂的实验设置详见 tools/notes/DevelopmentWorkflow.md 的Running the e2e Test Apps一节例如npx nx run apps-automated:ios npx nx run apps-automated:android六、小结与最佳实践清单综合原文档与仓库实际代码在该仓库中编写单元测试可以遵循以下清单位置测试文件以*.spec.ts命名与被测源码同目录放置运行npx nx run package:test需要实时反馈加--watch只想跑某一组用例用-t DescribeName过滤APIcore 包全局启用 Vitest 全局 APIimport { ... } from vitest可选vite 包globals: false需显式导入隔离用beforeEach重建被测对象、afterEach恢复全局状态避免用例间串扰异步直接写async函数并awaitPromise 后断言环境边界Node 环境下只有桩stub需要真机/原生运行时行为时移步 e2e 套件apps/automated等扩展桩当测试需要更多原生 API 时在packages/core/vitest.setup.ts中扩展 mock而不是在用例里临时修改全局。掌握以上规范后你可以为任何 core/vite 等包的模块补写规格测试并借助 Nx 的按包执行与测试名过滤能力在大型 workspace 中快速定位与验证行为。赞分享【免费下载链接】NativeScript⚡ Write Native with TypeScript ✨ Best of all worlds (TypeScript, Swift, Objective C, Kotlin, Java, Dart). Use what you love ❤️ Angular, React, Solid, Svelte, Vue with: iOS (UIKit, SwiftUI), Android (View, Jetpack Compose), Flutter and you name it compatible.项目地址https://gitcode.com/gh_mirrors/na/NativeScript点击查看免费下载相关推荐NativeScript 仓库单元测试编写指南基于 Vitest 与 Nx 的 *.spec.ts 测试实践NativeScript 仓库单元测试编写指南基于 Vitest 与 Nx 的 .spec.ts 测试实践 导读 本文面向 NativeScript 仓库的贡NativeScript 仓库单元测试编写指南基于 Vitest 的 .spec.ts 测试实践NativeScript 仓库单元测试编写指南基于 Vitest 的 .spec.ts 测试实践 本篇技术指南围绕 NativeScript 开源仓库monNativeScript 仓库单元测试编写指南Vitest、Nx 与 Node 环境下的平台模拟实践NativeScript 仓库单元测试编写指南Vitest、Nx 与 Node 环境下的平台模拟实践 导读 本文以 tools/notes/WritingUn上一篇Nuxt.js 项目中的 assets 目录详解静态资源管理指南下一篇h5py文件操作详解HDF5文件的高级使用指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表