
Playwright Test 中 FullProject 运行时项目配置对象详解从 TestInfo.project 到源码解析【免费下载链接】playwrightPlaywright is a framework for Web Testing and Automation. It allows testing Chromium, Firefox and WebKit with a single API.项目地址: https://gitcode.com/GitHub_Trending/pl/playwright本文围绕 Playwright 官方 API 文档中的FullProject类展开它是什么、与配置文件中的TestProject有何区别、包含哪些属性以及在测试代码TestInfo.project、WorkerInfo.project和测试报告器Reporter中如何消费它。读完本文你可以掌握如何在测试与自定义 Reporter 中读取已解析的项目级配置如testDir、outputDir、retries、use等并能结合 packages/playwright/src/common/config.ts 的源码理解每个属性的解析优先级与默认值。FullProject 的定位TestProject 的“运行时形态”Playwright Test 支持在一次运行中配置多个测试项目projects用于在不同浏览器、不同设备、不同目录下并行执行测试。项目配置的“书写格式”由TestProject描述完整的配置项说明见 TestProject 文档。而FullProject是测试项目配置的运行时表示官方文档定义since v1.10仅 JS/TS 语言支持Runtime representation of the test project configuration. It is accessible in the tests viaTestInfo.projectandWorkerInfo.projectand is passed to the test reporters.也就是说FullProject是 Playwright 在加载完配置文件、合并完全局配置与命令行参数之后交给运行时的“已解析”项目对象。它的三个主要消费方是测试代码通过TestInfo.project与WorkerInfo.project访问两者类型均为FullProject定义见 test.d.ts#L2586 与 test.d.ts#L10850测试报告器FullConfig.projects是FullProject[]数组见 test.d.ts#L2043Runner 内部FullProjectInternal类持有一个readonly project: FullProject用于调度 worker、计算输出目录等见 config.ts#L157-L167。FullProject的 TypeScript 接口完整定义在 test.d.ts#L770-L852。FullProject 完整属性一览官方文档class-fullproject.md列出了FullProject的全部 16 个属性每个属性均对应TestProject的同名配置项。与TestProject中多为可选?的声明不同FullProject中的属性都是已完成合并与默认值填充的确定值仅teardown例外仍为可选。下表汇总了各属性的运行时类型以及从源码 config.ts#L180-L199 中确认的解析优先级“项目级 → 全局配置 → 默认值”属性类型解析规则与默认值源码确认useFixturesmergeObjects(config.use, project.use, CLI use)即项目级use覆盖全局use命令行--参数优先级最高dependenciesArraystring直接取项目配置缺省为[]grepRegExp \| RegExp[]项目级 → 全局 → 默认/.*/匹配全部grepInvertnull \| RegExp \| RegExp[]项目级 → 全局 → 默认nullignoreSnapshotsboolean命令行覆盖 → 项目级 → 全局 → 默认false自 v1.59 起成为必填布尔值metadataMetadata项目级 → 全局 → 默认{}namestring项目级 → 全局 → 默认snapshotDirstringpathResolve(configDir, 项目级)→pathResolve(configDir, 全局)→ 回退为解析后的testDiroutputDirstring命令行 →pathResolve(configDir, 项目级)→pathResolve(configDir, 全局)→package.json 目录/test-resultsrepeatEachnumber项目级 → 全局 → 默认1retriesnumber命令行 → 项目级 → 全局 → 默认0teardown?string按项目配置原样传递可缺省testDirstringpathResolve(configDir, 项目级)→pathResolve(configDir, 全局)→ 配置文件所在目录testIgnorestring \| RegExp \| Arraystring \| RegExp项目级 → 全局 → 默认[]testMatchstring \| RegExp \| Arraystring \| RegExp项目级 → 全局 → 默认**/*.(spec|test).?(c|m)[jt]s?(x)timeoutnumber--debuginspector时强制0不超时→ 命令行 → 项目级 → 全局 → 默认 30000 毫秒30 秒从源码结构看FullProjectInternal构造函数正是这张表的逐行实现例如timeout一行takeFirst(configCLIOverrides.debug inspector ? 0 : undefined, configCLIOverrides.timeout, projectConfig.timeout, config.timeout, defaultTimeout)说明在 inspector 调试模式下项目超时会被自动取消。在测试代码中读取 TestInfo.project / WorkerInfo.projectTestInfo.project与WorkerInfo.project的类型均为FullProject可以直接读取上述任意属性。在 packages/playwright/src/worker/testInfo.ts#L122 中可以看到TestInfo持有readonly project: FullProject并在构造时直接引用FullProjectInternal.projecttestInfo.ts#L186-L187。一个典型的用法是依据项目名做差异化断言或日志import { test, expect } from playwright/test; test(read project config at runtime, ({ page }, testInfo) { // testInfo.project 即 FullProject console.log(项目名, testInfo.project.name); // 如 chromium console.log(超时, testInfo.project.timeout); // 已解析的毫秒数 console.log(输出目录, testInfo.project.outputDir); // 绝对路径 console.log(浏览器, testInfo.project.use.browserName); expect(testInfo.project.retries).toBe(0); });Worker 级 fixture 中同样可以通过workerInfo.project拿到同一对象适合在 worker 初始化阶段打印该项目配置。由于FullProject中的use是三层合并全局use 项目use 命令行后的结果测试代码里读到的testInfo.project.use.browserName永远是最终生效值而不是配置文件里某一层的原始值。在自定义 Reporter 中消费 FullProjectFullConfig.projects的类型是FullProject[]test.d.ts#L2043因此任何自定义 Reporter 在onBegin中都能拿到全部已解析项目。以下示例展示如何遍历项目并读取其配置// reporter.ts import type { FullConfig, Reporter, Suite } from playwright/test/reporter; class ProjectInspectorReporter implements Reporter { private _config: FullConfig | undefined; onBegin(config: FullConfig, suite: Suite) { this._config config; for (const project of config.projects) { // project 即 FullProject属性均已解析为确定值 console.log( [${project.name}] testDir${project.testDir} timeout${project.timeout}ms retries${project.retries} deps[${project.dependencies.join(, )}] ); } } onEnd(result: passed | failed | timedout) { console.log(run ${result}); } // 其余空实现从略 } export default function (): Reporter { return new ProjectInspectorReporter(); }配合配置文件的reporter数组即可加载。借助metadata属性解析后为Metadata对象还可以把自定义键值对透传到 Reporter 层实现项目维度的报表扩展。源码纵深FullProject 是如何被构造出来的理解FullProject的解析流程关键在 packages/playwright/src/common/config.ts项目列表来源FullConfigInternal构造时执行configCLIOverrides.projects || userConfig.projects || [{ ...userConfig, workers: undefined }]——即用户没有显式声明projects时会把整个全局配置包装成唯一的项目config.ts#L132-L134。随后为每个项目构造一个FullProjectInternal并把它们的project字段汇总为config.projects供测试与 Reporter 读取。属性合并FullProjectInternal构造函数config.ts#L169-L210对每个属性执行takeFirst(项目级, 全局级, 默认值)的三级回退并在需要相对路径语义的属性testDir、snapshotDir、outputDir上先做path.resolve(configDir, ...)转绝对路径。这正是FullProject与TestProject的核心差异你读到的testDir、outputDir、snapshotDir一定是绝对路径。唯一项目 ID_assignUniqueProjectIdsconfig.ts#L140-L154会给每个项目分配一个内部 ID重名项目会自动追加数字后缀chromium、chromium1…并挂到隐藏属性__projectId上通过getProjectId()工具函数读取config.ts#L311-L313。这解释了为什么name允许重复但依赖名必须唯一。依赖图校验resolveProjectDependenciesconfig.ts#L250-L282在加载阶段完成dependencies/teardown的解析与合法性校验任何配置错误都会在此直接抛错依赖了不存在的项目Project X depends on unknown project Y依赖/teardown 目标重名Project dependencies should have unique names, reading Yteardown 项目自身不允许再有依赖Teardown project X must not have dependencies普通项目不能依赖 teardown 项目Project X must not depend on a teardown project Y。这些约束正是 TestProject.dependencies 与 TestProject.teardown 文档中“setup/teardown 配对”模式的实现基础命令行传入--no-deps时则会忽略dependencies与teardown。运行时消费点TestInfo用this.project.timeout初始化超时管理器testInfo.ts#L199并基于project.outputDir/project.testDir/project.snapshotDir计算每个用例的输出与快照目录testInfo.ts#L204-L220。例如snapshotDir的解析规则是“snapshotDir 相对testDir的文件路径 -snapshots后缀”与 tests/library/screenshot.spec.ts-snapshots/ 等测试仓库中的快照目录命名一致。属性详解与实战建议结合 TestProject 文档 与源码解析链对FullProject各属性做要点归纳name在报告与控制台中可见注意 Playwright 会多次执行配置文件不要在配置中动态生成不稳定值官方文档对此有 warning。testDir递归扫描测试文件的目录默认配置文件所在目录每个项目可以指向不同目录实现“smoke 子集跑三浏览器、全量测试跑稳定 Chrome”这类常见拆分示例见 TestProject.testDir。testMatch/testIgnore按绝对文件路径匹配字符串按 glob 处理默认testMatch为**/*.(spec|test).?(c|m)[jt]s?(x)testIgnore默认空数组。grep/grepInvert正则作用于“项目名 文件名 describe名 测试名 标签”拼接成的字符串可用于测试标签tagging运行时读到的值已回退为/.*/或null。timeout基础超时 30 秒可被test.setTimeout与test.describe.configure在更细粒度覆盖--debuginspector时源码会直接置为0禁用超时。retries/repeatEach分别为失败重试次数默认 0与每次测试重复执行次数默认 1后者适合调试 flaky 测试。outputDir默认package.json 目录/test-results运行开始时清空每次测试在其下创建独立子目录测试中可用testInfo.outputPath()生成临时文件。snapshotDir默认回退为testDir可结合TestInfo.snapshotDir()/snapshotPath()定位快照。ignoreSnapshotstrue时跳过toMatchSnapshot与toHaveScreenshot等快照断言典型场景是“仅 Chromium 执行截图断言Firefox/WebKit 项目声明ignoreSnapshots: true”。metadata原样进入 JSON 报告的自定义数据默认空对象。dependencies/teardown成对使用时可把全局 setup/teardown 写成测试形式从而在报告中产出 trace 等产物其合法性约束由上文resolveProjectDependencies保证。use三层合并后的 fixture 选项集合是测试代码中获取浏览器、视口、trace 等最终生效配置的唯一入口。小结FullProject是 Playwright Test “配置层TestProject→ 运行层FullProject”之间的一座桥所有可选配置项在 FullProjectInternal 中经“项目级 → 全局级 → 默认值”的回退与路径解析后固化为确定值的运行时对象再分发给TestInfo.project、WorkerInfo.project与全部 Reporter。理解了这条解析链你就能在测试与自定义报告中可靠地读取任意项目级配置并在依赖报错时快速对照resolveProjectDependencies的校验规则定位配置问题。【免费下载链接】playwrightPlaywright is a framework for Web Testing and Automation. It allows testing Chromium, Firefox and WebKit with a single API.项目地址: https://gitcode.com/GitHub_Trending/pl/playwright创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考