Playwright TypeScript配置全解析:从零搭建自动化测试环境
1. 项目概述为什么Playwright跑TS脚本需要专属配置如果你是从Selenium或者Puppeteer转战Playwright或者刚开始接触Web自动化测试可能会遇到一个典型问题为什么我的JavaScript脚本跑得好好的换成TypeScript就报一堆找不到模块、语法错误的幺蛾子尤其是在使用Playwright Test这个官方测试运行器时直接运行一个.ts文件大概率会碰壁。这个问题的核心就在于Playwright的运行环境需要一个“翻译官”和“导航图”来理解并执行你的TypeScript代码。这个“导航图”就是playwright.config.ts或.js配置文件。简单来说Playwright Test是一个基于Node.js的测试运行器。Node.js原生只能执行JavaScript。当你写下import { test, expect } from playwright/test;这样的TypeScript代码时Node.js是看不懂的。我们需要一个“预处理”环节把TypeScript编译成JavaScript。这个预处理工作可以交给ts-node、tsx或者esbuild等工具。而playwright.config.ts文件正是告诉Playwright Test“嘿我这里的测试文件是TypeScript写的请你用我指定的这个编译器比如ts-node先处理一下再去执行。”所以配置playwright.config.ts不是可选项而是当你决定在Playwright项目中使用TypeScript时必须完成的基础设施搭建。它定义了项目的“游戏规则”在哪里找测试文件、用什么浏览器、如何编译TypeScript、测试失败时要不要截图录屏、用什么报告格式等等。没有它Playwright Test就像失去了操作手册无法正确处理你的TS脚本。2. 核心需求解析从零搭建一个TS驱动的Playwright项目要跑通一个TypeScript的Playwright脚本我们的目标不仅仅是“能运行”而是要建立一个可靠、可维护、高效的自动化测试环境。这背后对应着几个核心需求2.1 类型安全与开发体验TypeScript的核心价值是静态类型检查。在编写元素定位器如page.locator(button)或断言如expect(title).toContainText(Hello)时我们希望编辑器能提供智能补全、参数提示并在编码阶段就发现潜在的类型错误比如错误地使用了click方法的参数。这能极大减少运行时错误提升代码质量。2.2 统一的测试执行与报告我们需要一个统一的命令如npx playwright test来执行所有测试并能够方便地按标签、按文件名过滤测试用例。测试完成后需要清晰直观的报告如HTML报告、Allure报告来查看通过率、失败原因、执行日志和录屏便于问题追溯。2.3 可配置的运行环境不同的测试场景需要不同的配置本地调试时可能想用headed模式看着浏览器跑CI/CD流水线中则需要无头模式可能需要对某些慢动作设置更长的超时时间或者需要为不同的项目配置不同的基础URL。这些灵活多变的配置项需要一个中心化的地方来管理。2.4 高效的编译与执行流程我们不希望每次修改代码后都要手动执行一次tsc编译再去运行生成的.js文件。理想的流程是修改*.spec.ts文件后保存然后一条命令就能直接运行最新的测试。这要求我们的配置能集成一个快速的TypeScript执行器。基于以上需求一个标准的Playwright TypeScript项目配置就需要围绕playwright.config.ts文件展开解决编译、执行、报告、环境配置等一系列问题。3. 环境准备与项目初始化在开始配置之前确保你的本地环境已经就绪。这里假设你从零开始。3.1 Node.js与包管理器首先你需要安装Node.js建议LTS版本如18.x或20.x。Node.js自带了npm包管理器。你也可以选择yarn或pnpm它们在某些场景下速度更快。本文将以npm为例。打开终端检查安装是否成功node --version npm --version3.2 初始化项目并安装Playwright创建一个新的项目目录并进入然后初始化npm项目。这里我们直接生成一个package.json文件。mkdir my-playwright-project cd my-playwright-project npm init -y接下来安装Playwright的核心测试库。使用--save-dev将其作为开发依赖安装。npm install --save-dev playwright/test3.3 安装Playwright浏览器Playwright需要它自己管理的浏览器二进制文件Chromium, Firefox, WebKit来运行测试。安装核心库时不会自动下载浏览器。你需要运行以下命令来安装npx playwright install这个命令会下载所有三个浏览器Chromium, Firefox, WebKit到本地缓存中。如果你只想安装特定的浏览器可以加上参数例如npx playwright install chromium。注意第一次安装浏览器可能会比较慢因为需要从网络下载几百MB的文件。如果遇到网络问题可以尝试设置环境变量PLAYWRIGHT_DOWNLOAD_HOST使用国内镜像源或者使用--with-deps参数并配置npm镜像。例如在某些网络环境下可以尝试npm config set registry https://registry.npmmirror.com/ npx playwright install --with-deps3.4 安装TypeScript及相关依赖现在安装TypeScript编译器以及让Playwright能够直接运行TS的工具。最常用的组合是typescript和ts-node。npm install --save-dev typescript ts-node types/nodetypescript: TypeScript编译器本身。ts-node: 一个TypeScript执行引擎可以直接在Node.js中运行.ts文件无需预先编译成.js。types/node: 提供Node.js API的类型定义让TS能识别process,setTimeout等Node原生模块。初始化TypeScript配置生成tsconfig.json文件npx tsc --init生成的tsconfig.json文件包含了很多默认配置。对于Playwright项目我们通常需要调整其中几项。4. 核心配置文件详解playwright.config.ts这是整个项目的“大脑”。Playwright Test运行时会自动在项目根目录寻找这个文件。让我们一步步拆解一个功能完备的配置。4.1 基础结构搭建首先在项目根目录创建playwright.config.ts文件。Playwright配置支持TypeScript所以我们直接使用.ts后缀以便在配置中也能享受类型提示。打开playwright.config.ts开始编写import { defineConfig, devices } from playwright/test; /** * 阅读 https://playwright.dev/docs/test-configuration 了解更多信息。 */ export default defineConfig({ // 测试文件所在的目录。可以使用全局模式。 testDir: ./tests, // 匹配所有测试文件的最大超时时间毫秒。 timeout: 30 * 1000, // 每个测试用例的默认超时时间毫秒。 expect: { timeout: 5000 }, // 并行运行测试。可以设置为 false 以禁用或指定最大并行工作进程数。 fullyParallel: true, // 在CI环境中如果测试失败则禁止重试以便快速反馈。 forbidOnly: !!process.env.CI, // 失败测试的重试次数。在CI中设置得更高一些有助于稳定性。 retries: process.env.CI ? 2 : 0, // 并行运行测试的工作进程数。可以指定一个数字或使用 50% 来使用一半的CPU核心。 workers: process.env.CI ? 1 : 50%, // 测试报告器html 会生成漂亮的本地HTML报告。 reporter: html, // 项目级别的配置允许你针对不同的浏览器或设备运行测试。 projects: [ { name: chromium, use: { ...devices[Desktop Chrome] }, }, { name: firefox, use: { ...devices[Desktop Firefox] }, }, { name: webkit, use: { ...devices[Desktop Safari] }, }, ], // 全局运行测试前/后可以执行的脚本常用于启动/停止服务器。 // webServer: { // command: npm run start, // url: http://127.0.0.1:3000, // reuseExistingServer: !process.env.CI, // }, // 最重要的部分告诉Playwright如何运行你的TypeScript文件。 use: { // 基础URL这样在测试中可以使用相对路径如 await page.goto(/admin); baseURL: http://localhost:3000, // 收集执行失败时的追踪信息。on-first-retry表示只在第一次重试时收集以平衡信息量和性能。 trace: on-first-retry, // 收集执行失败时的截图。only-on-failure表示只在失败时截图。 screenshot: only-on-failure, // 收集执行失败时的视频。retain-on-failure表示失败时保留视频成功则删除。 video: retain-on-failure, }, });4.2 关键配置项深度解析testDir: ‘./tests’: 指定你的测试用例文件存放的目录。Playwright会递归查找这个目录下所有匹配.*(test|spec)\.(js|ts|mjs)模式的文件。你可以根据习惯改为./e2e或./specs。timeout与expect.timeout: 这是两个容易混淆的超时设置。timeout是针对整个测试文件的最大执行时间从test.beforeAll到test.afterAll。expect.timeout是针对单个断言如expect(locator).toBeVisible()的等待时间。根据你的应用响应速度合理设置本地调试可以设长些CI环境可以设短些以快速失败。fullyParallel与workers: 这是Playwright强大的并发测试能力。fullyParallel: true允许同一个文件内的不同测试用例并行运行。workers控制并行的工作进程数。‘50%’意味着使用一半的CPU核心数。注意并行测试要求测试用例之间是独立的不能有共享状态如依赖同一个全局变量。在CI环境中有时为了稳定性会设置为workers: 1。forbidOnly与retries:test.only()用于只运行一个测试在提交代码时务必避免。forbidOnly: !!process.env.CI确保在CI环境中如果存在.only测试则会失败。retries用于重试失败的测试对于处理网络抖动或测试环境不稳定的“脆性测试”很有用。在CI中设置为2可以增加通过率但会掩盖真正的稳定性问题需谨慎使用。projects: 这是Playwright配置的精华。它允许你定义多套测试环境。上面的例子定义了三个项目分别针对三大浏览器。你可以轻松地只运行npx playwright test --projectchromium。你还可以在这里为移动端‘iPhone 13’、不同视口、不同权限如地理位置等定义不同的项目。use: 这里定义的选项会应用到所有测试中。baseURL非常实用它允许你在测试中使用相对路径。trace,screenshot,video是强大的调试三件套。我强烈建议至少开启trace: ‘on-first-retry’和screenshot: ‘only-on-failure’。Trace文件可以在Playwright Trace Viewer (npx playwright show-trace)中可视化地回放整个测试操作是排查“为什么点击没反应”这类问题的神器。4.3 配置TypeScript支持上面的配置已经可以运行JS文件了但对于TS文件我们还需要关键一步告诉Playwright使用ts-node或其他加载器来预处理.ts文件。这通常不需要在playwright.config.ts中显式设置因为Playwright Test会自动检测到项目根目录存在tsconfig.json文件并尝试使用ts-node/register来加载TS文件。但是为了更明确和应对一些复杂情况我们可以在配置中指定加载器。修改或添加以下配置export default defineConfig({ // ... 其他配置 ... // 指定用于加载测试文件的加载器。对于TypeScript项目ts-node是常见选择。 // 从Playwright 1.28版本开始通常不需要显式设置除非遇到问题。 // loader: { // .ts: ts-node, // }, // 更重要的是确保你的 tsconfig.json 配置正确。 });真正的关键在于tsconfig.json的配置。打开之前生成的tsconfig.json进行如下关键调整{ compilerOptions: { target: ES2022, // 或更新版本匹配现代Node.js特性 module: commonjs, // Playwright Test 运行在Node.js环境通常使用CommonJS lib: [ES2022, DOM], // 包含DOM类型定义因为我们在测试中操作浏览器DOM outDir: ./dist, // 编译输出目录如果使用tsc编译 rootDir: ./, // 源代码根目录 strict: true, // 启用所有严格类型检查选项 esModuleInterop: true, // 允许与CommonJS模块的互操作性 skipLibCheck: true, // 跳过库文件的类型检查加速编译 forceConsistentCasingInFileNames: true, resolveJsonModule: true // 允许导入JSON文件 }, include: [ tests/**/*.ts, // 包含所有测试文件 playwright.config.ts // 包含配置文件本身 ], exclude: [ node_modules, dist // 排除输出目录 ] }最重要的几项是“module”: “commonjs”和“lib”中包含“DOM”。commonjs确保编译后的模块系统与Node.js兼容。DOM库提供了window,document,HTMLElement等浏览器环境类型这样你在写page.evaluate()等代码时就不会报类型错误。5. 编写并运行第一个TypeScript测试脚本配置完成后让我们写一个简单的测试来验证一切是否正常。5.1 创建测试目录和文件根据配置中的testDir: ‘./tests’创建目录和测试文件mkdir tests touch tests/example.spec.ts5.2 编写测试用例打开tests/example.spec.ts写入以下内容import { test, expect } from playwright/test; // 一个简单的测试用例 test(has title, async ({ page }) { // 导航到Playwright官网 await page.goto(https://playwright.dev/); // 断言页面标题包含“Playwright” await expect(page).toHaveTitle(/Playwright/); }); // 另一个测试用例演示定位器和交互 test(get started link, async ({ page }) { await page.goto(https://playwright.dev/); // 点击“Get started”链接 const getStarted page.getByRole(link, { name: Get started }); await getStarted.click(); // 断言URL包含“/docs/intro” await expect(page).toHaveURL(/.*intro/); });5.3 运行测试现在在终端运行以下命令npx playwright test如果一切配置正确你将看到Playwright启动浏览器默认无头模式运行两个测试并在控制台输出结果。运行完成后它会提示你HTML报告已生成通常可以通过npx playwright show-report来打开一个漂亮的本地HTML报告查看详细的测试结果、时间线、以及我们配置的截图和Trace如果失败。5.4 带UI运行测试如果你想看着浏览器执行可以添加--headed参数npx playwright test --headed5.5 运行特定浏览器如果你想只针对Chrome运行测试可以使用--project参数npx playwright test --projectchromium6. 高级配置与优化技巧基础配置能跑通但要打造一个高效的测试工程还需要一些进阶配置。6.1 环境变量与多环境配置我们经常需要区分本地、测试、生产环境。环境变量是很好的方式。可以在playwright.config.ts中动态读取import { defineConfig, devices } from playwright/test; // 从环境变量读取基础URL默认为开发环境 const baseURL process.env.BASE_URL || http://localhost:3000; // 判断是否为CI环境 const isCI !!process.env.CI; export default defineConfig({ use: { baseURL, trace: isCI ? on-first-retry : on, screenshot: isCI ? only-on-failure : on, }, retries: isCI ? 2 : 0, workers: isCI ? 1 : 50%, // ... 其他配置 });然后运行测试时传入环境变量BASE_URLhttps://staging.example.com npx playwright test # 或者在CI脚本中设置 CItrue CItrue npx playwright test6.2 使用ESBuild提升执行速度ts-node在开发时很方便但在CI中或需要更快启动时esbuild是更快的选择。你需要安装playwright/test的esbuild插件如果版本支持或手动配置。 首先安装esbuild和相关插件npm install --save-dev esbuild esbuild-register然后在playwright.config.ts中配置加载器注意具体配置方式可能随Playwright版本变化请查阅最新文档export default defineConfig({ // Playwright 1.40 版本可以这样配置 // build: { // // 使用esbuild打包测试文件实验性功能 // // 这可以显著提升大型测试套件的启动速度 // }, // 或者通过loader配置如果支持 // loader: { // .ts: esbuild-register/register, // }, // ... 其他配置 });更常见的做法是在CI流水线中先使用tsc或esbuild将整个项目编译成JavaScript然后直接运行编译后的.js文件这样可以完全避免运行时的编译开销。6.3 配置全局Setup与Teardown有些操作需要在所有测试运行前/后执行一次比如登录获取认证token、初始化数据库、启动本地服务器。这可以通过globalSetup和globalTeardown选项实现。 首先创建一个全局设置文件例如tests/global-setup.ts// tests/global-setup.ts import { FullConfig } from playwright/test; async function globalSetup(config: FullConfig) { // 例如从环境变量或外部服务获取一个认证令牌 const token process.env.AUTH_TOKEN; // 将这个令牌存储起来供所有测试项目使用 process.env.AUTH_TOKEN_FOR_TESTS token; // 或者启动一个本地开发服务器 // const server startServer(); // await server.ready(); // globalThis.__SERVER__ server; } export default globalSetup;然后在playwright.config.ts中引用它export default defineConfig({ globalSetup: require.resolve(./tests/global-setup.ts), // ... 其他配置 });globalTeardown的配置方式类似用于清理资源。6.4 配置Web Server如果你的测试依赖于一个本地开发服务器Playwright可以帮你自动启动和停止。这在playwright.config.ts中非常方便export default defineConfig({ // ... 其他配置 webServer: { command: npm run dev, // 启动服务器的命令 url: http://localhost:3000, // 用于检测服务器是否就绪的URL timeout: 120 * 1000, // 启动超时时间毫秒 reuseExistingServer: !process.env.CI, // 非CI环境下如果服务器已在运行则复用 stdout: pipe, // 或 ignore将服务器日志输出到标准输出 stderr: pipe, }, });这样当你运行npx playwright test时Playwright会先执行npm run dev并不断轮询http://localhost:3000直到收到成功响应如200状态码然后再开始运行测试。测试结束后它会终止这个服务器进程除非reuseExistingServer为true且服务器已存在。7. 常见问题排查与实战心得即使配置正确在实际操作中还是会遇到各种问题。这里记录一些高频问题和解决思路。7.1 错误Cannot find module ‘playwright/test’ 或其类型声明症状在*.spec.ts文件中import { test, expect } from ‘playwright/test’;这一行报红提示找不到模块。原因没有安装playwright/test包。运行npm list playwright/test检查。TypeScript的tsconfig.json中moduleResolution设置不正确。对于Node.js项目应设置为“node”这是“commonjs”模块下的默认值。VS Code使用的TypeScript版本不是项目本地的。按下CtrlShiftP输入“TypeScript: Select TypeScript Version”选择“Use Workspace Version”。解决确保已运行npm install --save-dev playwright/test。在tsconfig.json中检查或添加“moduleResolution”: “node”。重启VS Code的TypeScript语言服务。7.2 错误ts-node 未安装或配置失败症状运行npx playwright test时报错Cannot find module ‘ts-node’或类似加载错误。原因Playwright尝试用ts-node加载.ts文件但ts-node未安装或版本不兼容。解决运行npm install --save-dev ts-nodelatest确保已安装。如果问题依旧可以尝试在playwright.config.ts中显式禁用自带加载器并使用playwright/test的experimental的ct组件测试配置中的加载器或者回退到先编译再运行的方式在package.json中添加脚本“build:tests”: “tsc -p tsconfig.json”然后运行npm run build:tests npx playwright test dist/tests/。7.3 测试运行缓慢尤其是首次运行症状第一次运行测试或者清理缓存后运行启动非常慢。原因ts-node每次运行都需要编译TypeScript有一定开销。Playwright浏览器启动本身需要时间。优化使用esbuild如前所述用esbuild-register替代ts-node可以显著提升启动速度。预热在CI流水线中可以添加一个预热步骤先运行一个最简单的测试如test(‘warmup’, () {})让浏览器和编译缓存加载起来。复用浏览器上下文在测试中如果测试用例是独立的尽量复用browser和context而不是为每个测试都重新启动。Playwright Test的test.beforeAll和test.afterAll钩子可以帮助管理共享状态。7.4 HTML报告中没有视频或Trace症状测试失败了但HTML报告里看不到视频或Trace文件或者提示文件找不到。原因配置中未开启video和trace选项或开启的时机不对如trace: ‘off’。输出目录test-results被清理了。路径配置问题。解决确保配置中至少设置了trace: ‘on-first-retry’和video: ‘retain-on-failure’。检查playwright.config.ts中的outputDir配置默认是test-results确保该目录存在且可写。运行测试时使用--trace on和--video on参数可以强制开启会覆盖配置文件。7.5 在CI/CD中运行Playwright TS测试的最佳实践在CI环境中稳定性、速度和资源消耗是关键。缓存充分利用CI系统的缓存功能缓存node_modules、Playwright浏览器二进制文件~/.cache/ms-playwright以及可能的编译输出目录如dist。这能极大缩短流水线时间。依赖安装使用npm ci代替npm install它能根据package-lock.json提供确定性的安装更快更可靠。并行与分片使用Playwright的shard功能可以将测试套件分割成多个分片在多个CI机器上并行运行。命令如npx playwright test --shard1/3。使用官方Docker镜像Playwright提供了官方的Docker镜像如mcr.microsoft.com/playwright里面已经预装了所有依赖和浏览器可以避免环境不一致问题。资源清理CI任务结束后确保清理掉生成的test-results、playwright-report等目录除非你需要归档它们。7.6 一个实用的、功能齐全的配置模板最后分享一个我经过多个项目锤炼后觉得比较实用的playwright.config.ts模板。它集成了环境变量、多项目、Web服务器、报告和性能优化考量。import { defineConfig, devices } from playwright/test; import path from path; // 从环境变量读取配置提供默认值 const baseURL process.env.PLAYWRIGHT_TEST_BASE_URL || http://localhost:3000; const isCI !!process.env.CI; const isHeadless process.env.HEADLESS ! false; // 默认无头可通过 HEADLESSfalse 覆盖 const traceMode process.env.TRACE_MODE || (isCI ? on-first-retry : on); const videoMode process.env.VIDEO_MODE || (isCI ? retain-on-failure : off); export default defineConfig({ testDir: ./tests, outputDir: ./test-results, timeout: 60 * 1000, // 全局超时设长一些应对复杂场景 expect: { timeout: 10000 }, // 单个断言超时10秒 fullyParallel: true, // 充分利用并行 forbidOnly: isCI, // CI环境下禁止 test.only retries: isCI ? 2 : 1, // CI下重试2次本地重试1次帮助发现脆性测试 workers: isCI ? 2 : 75%, // CI下固定2个worker本地用75%的CPU核心 reporter: [ [list], // 简洁的控制台输出 [html, { outputFolder: playwright-report, open: never }], // 生成HTML报告不自动打开 isCI ? [blob] : [], // CI环境下生成blob报告可用于上传到Playwright云服务 ], use: { baseURL, trace: traceMode, screenshot: only-on-failure, video: videoMode as off | on | retain-on-failure, // 类型断言 actionTimeout: 15000, // 每个操作click, fill的超时 navigationTimeout: 30000, // 页面导航的超时 viewport: { width: 1920, height: 1080 }, // 统一的视口大小 ignoreHTTPSErrors: true, // 忽略HTTPS证书错误便于测试内部环境 }, projects: [ // 桌面端 Chrome 测试 { name: chromium, use: { ...devices[Desktop Chrome], channel: chrome, // 使用系统安装的Chrome而非Chromium }, }, // 桌面端 Firefox 测试 { name: firefox, use: { ...devices[Desktop Firefox] }, // 可以针对特定项目设置不同的重试策略或超时 // retries: 0, }, // 移动端 Chrome 测试 (模拟) { name: Mobile Chrome, use: { ...devices[Pixel 5] }, }, // 一个专门用于API测试的项目不需要浏览器 { name: api, testMatch: /.*\.api\.spec\.ts/, // 只运行以 .api.spec.ts 结尾的文件 use: { baseURL: process.env.API_BASE_URL || baseURL, }, }, ], // 本地开发服务器 webServer: !isCI ? { command: npm run dev, url: baseURL, timeout: 120 * 1000, reuseExistingServer: true, stdout: pipe, stderr: pipe, } : undefined, });这个模板提供了良好的默认值并通过环境变量实现了高度的可配置性。你可以将它复制到你的项目中根据实际情况微调它应该能覆盖绝大多数Web自动化测试场景的需求。记住配置不是一成不变的随着项目复杂度的增加你需要持续调整和优化它。