尧图精选

Vitest browser.instances 多浏览器配置详解:从声明到单一 Vite 服务编排

🕒 发布时间:2026/9/14 22:28:52 📁 来源:尧图网络
Vitest browser.instances 多浏览器配置详解从声明到单一 Vite 服务编排【免费下载链接】vitestNext generation testing framework powered by Vite.项目地址: https://gitcode.com/GitHub_Trending/vi/vitestbrowser.instances是 Vitest 浏览器模式下用于声明多套浏览器运行环境的配置项让你在一个项目中同时针对多个浏览器或同一浏览器的多套差异化配置运行同一批测试且所有实例共享同一个 Vite 服务以最大化缓存收益。读完本文你将掌握browser.instances的完整配置语法、可用字段、根配置继承规则、--project过滤用法以及 Vitest 在底层如何把实例展开为独立测试项目。什么是 browser.instancesbrowser.instances允许你在单个 Vitest 配置中定义多套浏览器运行方案。每个配置项至少需要包含一个browser字段浏览器名称其余字段可按需声明。Type:BrowserConfig[]Default:[]在源码中该项被定义为BrowserInstanceOption[]见 packages/vitest/src/node/types/browser.ts其类型由两部分组合而成export interface BrowserInstanceOption extends OmitProjectConfig, UnsupportedProperties, Pick BrowserConfigOptions, | headless | locators | viewport | testerHtmlPath | screenshotDirectory | screenshotFailures { browser: string name?: string provider?: BrowserProviderOption }从类型定义可以清楚地看到实例支持的配置范围它既继承了ProjectConfig中的绝大部分项目选项又单独挑出了部分browser级选项。类型中被明确排除的UnsupportedProperties包括browser、typecheck、alias、sequence、root、pool、runner、api、deps、environment、environmentOptions、server、benchmark、name等这意味着实例内部不能再次嵌套browser、不能自定义 runner、不能更换环境等而name是通过单独字段而非 project 的name提供的。为什么不用 test projects使用browser.instances相对于 test projects 的主要优势在于缓存每个实例共享同一个 Vite 服务文件转换transform和依赖预打包dependency pre-bundling只需执行一次而多个 test projects 会各自创建独立的 Vite 服务。这一点在原文档末尾也有明确说明Vitest 在底层会把实例转换为共享同一个 Vite 服务器的独立 test projects以获得更好的缓存性能。根配置继承规则重要警告每一个浏览器实例都会继承根配置中的选项。这意味着根配置中声明的setupFiles、browser选项等会自动应用到所有实例上实例自身声明的字段会与根配置合并而不是覆盖。以下为原文档给出的示例vitest.config.tsexport default defineConfig({ test: { setupFile: [./root-setup-file.js], browser: { enabled: true, testerHtmlPath: ./custom-path.html, instances: [ { // will have both setup files: root and browser setupFile: [./browser-setup-file.js], // implicitly has testerHtmlPath from the root config // testerHtmlPath: ./custom-path.html, }, ], }, }, })注意代码中的两个要点实例最终会同时加载./root-setup-file.js和./browser-setup-file.js两个 setup 文件而非仅加载实例自己声明的那个testerHtmlPath会隐式继承自根配置注释中被标记// [!code warning]的行即代表这一隐含行为。从源码看这种继承/合并逻辑实现在cloneProjectConfigForBrowserInstance函数中packages/vitest/src/node/projects/resolveProjects.ts它先对父项目配置做一次深拷贝deepClone(parentConfig)然后把实例中声明的browser、locators、viewport、testerHtmlPath、headless、screenshotDirectory、screenshotFailures、provider等字段逐个用「实例有值则用实例值否则回退到父配置」的方式合并进去。更关键的是 include/exclude 的处理// If there is no include or exclude or includeSource pattern in browser.instances[], // we should use the thats pattern from the parent project include: (overrideConfig.include overrideConfig.include.length 0) ? [] : clonedConfig.include, exclude: (overrideConfig.exclude overrideConfig.exclude.length 0) ? [] : clonedConfig.exclude, includeSource: (overrideConfig.includeSource overrideConfig.includeSource.length 0) ? [] : clonedConfig.includeSource,也就是说如果实例没有自定义include/exclude/includeSource会沿用父项目的匹配模式此时置空避免与父项目重复展开只有实例显式声明了这些字段时才以实例自身为准。实例可用的 browser 选项每个实例除了可以配置大多数 project options不带 图标标注的还可以配置以下browser选项选项说明文档browser浏览器名称必填—headless是否以无头模式运行默认process.env.CIheadlesslocatorsLocator 选项testIdAttribute、exact、errorFormat默认data-testid/false/alllocatorsviewport视口尺寸默认414 × 896viewporttesterHtmlPath用于运行测试的index.html路径testerHtmlPathscreenshotDirectory截图保存目录默认__screenshots__screenshotDirectoryscreenshotFailures测试失败时是否自动截图默认!browser.uiscreenshotFailuresprovider浏览器提供方playwright / preview / webdriverioprovider其中browser字段是必需的。若某个实例缺少browser字段Vitest 在解析配置时会直接抛出错误。相关校验逻辑位于 packages/vitest/src/node/projects/resolveProjects.tsif (!browser) { const nth index 1 const ending nth 2 ? nd : nth 3 ? rd : th throw new Error(The browser configuration must have a browser property. The ${nth}${ending} item in browser.instances doesnt have it. ...) }场景一同一套测试跑多个浏览器最典型的用法是用browser.instances把同一批测试分别跑在 Chromium、Firefox 和 WebKit 上最小配置如下来自 Multiple Setups 指南import { defineConfig } from vitest/config import { playwright } from vitest/browser-playwright export default defineConfig({ test: { browser: { enabled: true, provider: playwright(), headless: true, instances: [ { browser: chromium }, { browser: firefox }, { browser: webkit }, ], }, }, })运行vitest时Vitest 会自动把这 3 个实例展开为 3 个独立的测试项目在共享的 Vite 服务上分别执行。仓库的浏览器测试套件本身就是这样的实践例如 test/browser/settings.ts 中定义了 playwright 提供方下的三个默认实例const playwrightInstances: BrowserInstanceOption[] [ { browser: chromium }, { browser: firefox }, // hard to setup playwright webkit on some machines (e.g. ArchLinux) // this allows skipping it locally by BROWSER_NO_WEBKITtrue ...(process.env.BROWSER_NO_WEBKIT ? [] : [{ browser: webkit as const }]), ]注意当使用preview提供方且未声明任何实例时Vitest 会默认填充{ browser: chromium }见 packages/vitest/src/node/config/resolveConfig.ts。场景二同一浏览器下的多套差异化配置实例的browser字段是可选的与项目选项同级因此你还可以针对同一个浏览器声明多套不同的配置比如不同的 setup 文件、不同的 provide 注入值。下面这个示例来自 Multiple Setups 指南::: code-groupimport { defineConfig } from vitest/config import { playwright } from vitest/browser-playwright export default defineConfig({ test: { browser: { enabled: true, provider: playwright(), headless: true, instances: [ { browser: chromium, name: chromium-1, setupFiles: [./ratio-setup.ts], provide: { ratio: 1, }, }, { browser: chromium, name: chromium-2, provide: { ratio: 2, }, }, ], }, }, })import { expect, inject, test } from vitest import { globalSetupModifier } from ./example.js test(ratio works, () { expect(inject(ratio) * globalSetupModifier).toBe(14) }):::在这个例子中Vitest 会用chromium浏览器运行所有测试但只有第一个配置会执行./ratio-setup.ts文件并根据provide字段向测试注入不同的ratio值。测试端通过inject(ratio)读取注入值——由于两个实例对同一测试文件各自产生一次运行ratio分别为 1 和 2与globalSetupModifier假设为 7相乘后分别得到 7 和 14。同名浏览器的 name 要求::: warning 如果你对同一个浏览器声明了多个实例必须为它们定义自定义name否则 Vitest 会直接用浏览器名作为项目名导致项目名冲突。 :::从源码可以确认这一点expandBrowserInstancesInEntries中对每个展开的实例都会检查项目名唯一性重复时抛出错误packages/vitest/src/node/projects/resolveProjects.tsif (names.has(name)) { throw new Error( [ Cannot define a nested project for a ${browser} browser. The project name ${name} was already defined. , If you have multiple instances for the same browser, make sure to define a custom name. , All projects should have unique names. Make sure your configuration is correct., ].join(), ) } names.add(name)实例名称的自动生成规则未显式声明name时Vitest 在解析配置阶段会自动生成项目名规则位于 packages/vitest/src/node/config/resolveConfig.tsbrowser.instances.forEach((instance) { instance.name ?? resolved.name ? ${resolved.name} (${instance.browser}) : instance.browser })即根项目没有name时实例名就是浏览器名如chromium根项目有name如custom时实例名合并为custom (chromium)这种形式。场景三用 --project 过滤实例展开后的每个实例都是一个独立项目因此可以用--project标志来筛选要运行的浏览器。Vitest 会自动把浏览器名或上面规则生成的项目名作为项目名。$ vitest --projectchromium以下两个示例展示了默认命名与根配置已有name时的差异来自 Multiple Setups 指南::: code-groupexport default defineConfig({ test: { browser: { instances: [ // name: chromium { browser: chromium }, // name: custom { browser: firefox, name: custom }, ] } } })export default defineConfig({ test: { name: custom, browser: { instances: [ // name: custom (chromium) { browser: chromium }, // name: manual { browser: firefox, name: manual }, ] } } }):::从源码看--project过滤发生在实例展开阶段packages/vitest/src/node/projects/resolveProjects.ts父项目如果被过滤掉会整体丢弃如果父项目匹配但实例未匹配则只保留匹配的实例继续展开。展开后父项目会以hidden: true的形式保留在条目列表中用于创建TestProject实例通过_parent关联到它供浏览器提供方使用而实例名会取代父项目名出现在面向用户的项目列表中。底层原理实例如何被展开为共享 Vite 服务的项目整个「实例 → 项目」的转换由expandBrowserInstancesInEntries函数驱动packages/vitest/src/node/projects/resolveProjects.ts其核心流程可概括为分离条目将启用了browser.enabled的条目与普通条目分开普通条目保持原样读取实例取出projectConfig.browser.instances若为空或被--project过滤则丢弃整个浏览器项目逐实例展开对每个实例校验browser字段与name唯一性然后调用cloneProjectConfigForBrowserInstance克隆父配置并合并实例字段生成新的项目条目共享 Vite 配置展开出的所有实例条目共享同一个viteConfig代码中viteConfig, // shared with parent这就是「单一 Vite 服务、文件转换与依赖预打包只做一次」的实现根基。相关校验provider 一致性由于整个项目共享同一个浏览器 Vite 服务所有实例必须使用同一个 provider。如果配置中混用了不同 provider或同名但工厂函数不同Vitest 会在解析配置时直接报错packages/vitest/src/node/config/resolveConfig.tsif (providerNames.size 1 || providerFactories.size 1) { throw new Error( All browser instances within a project must use the same provider, but found: ${[...providerNames].join(, )}. Use a single provider for the project, or move the instances into separate projects., ) }此外在展开阶段还有一层针对 provider 的约束如果某个实例指定了与父项目不同的 provider同样会抛出错误packages/vitest/src/node/projects/resolveProjects.ts。同时preview提供方下的多浏览器配置以及--inspect调试模式、v8 coverage 组合存在功能限制遇到时会抛出带修正建议的明确错误信息例如提示改用playwrightprovider 或改用istanbulcoverage。实践要点小结必填项每个实例必须包含browser字段否则配置解析直接失败。继承语义实例自动继承根配置的setupFiles、browser选项等实例字段与根配置合并而非整体覆盖。同名浏览器必须自定义name否则项目名冲突报错未自定义时项目名默认取浏览器名根项目有name时合并为name (browser)形式。统一 provider同一项目下所有实例必须使用同一个 provider。过滤与调试用vitest --projectbrowser精确定位某个浏览器运行由于实例展开后共享 Vite 服务跨浏览器测试的文件转换开销只发生一次。更多完整示例可继续阅读 Multiple Setups 指南其配置对应的真实测试代码可参考 test/browser/settings.ts 与 test/browser/fixtures/browser-multiple/vitest.config.ts。【免费下载链接】vitestNext generation testing framework powered by Vite.项目地址: https://gitcode.com/GitHub_Trending/vi/vitest创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联 返回资讯列表 →