如何在VS Code中用Playwright+Cucumber+TypeScript结合POM搭建自动化项目
Playwright + Cucumber + POM + TypeScript 完整实现方案
一、标准项目文件夹结构
playwright-cucumber-pom-ts/ ├── features/ # Cucumber Feature文件(按业务模块划分) │ ├── auth/ │ │ └── login.feature │ └── dashboard/ │ └── dashboard_navigation.feature ├── src/ │ ├── pages/ # POM页面类(封装页面元素与操作) │ │ ├── basePage.ts # 基础页面类,封装通用操作 │ │ ├── loginPage.ts │ │ └── dashboardPage.ts │ ├── step-definitions/ # 步骤定义文件(与Feature一一对应) │ │ ├── authSteps.ts │ │ └── dashboardSteps.ts │ ├── test-data/ # 测试数据文件(按模块分类存储) │ │ ├── authData.json │ │ └── dashboardData.json │ ├── utils/ # 工具类(数据读取、通用方法) │ │ └── testDataUtils.ts │ └── cucumber.conf.ts # Cucumber核心配置 ├── playwright.config.ts # Playwright配置 ├── package.json └── tsconfig.json
二、端到端实现流程
1. 初始化项目与安装依赖
npm init -y # 安装Playwright核心依赖 npm install @playwright/test playwright # 安装Cucumber与TypeScript相关依赖 npm install @cucumber/cucumber typescript ts-node @types/node @types/cucumber --save-dev
2. 配置TypeScript与Cucumber
tsconfig.json(TypeScript编译配置):
{ "compilerOptions": { "target": "ES2020", "module": "CommonJS", "strict": true, "esModuleInterop": true, "skipLibCheck": true, "outDir": "./dist", "rootDir": "./src" }, "include": ["src/**/*", "features/**/*"] }
cucumber.conf.ts(Cucumber执行配置):
import { defineConfig } from '@cucumber/cucumber'; export default defineConfig({ requireModule: ['ts-node/register'], require: ['src/step-definitions/**/*.ts'], paths: ['features/**/*.feature'], format: ['progress-bar', 'html:cucumber-report.html'], // 生成测试报告 });
3. 编写POM页面类
先封装BasePage(通用操作复用):
import { Page, Locator } from '@playwright/test'; export class BasePage { protected page: Page; constructor(page: Page) { this.page = page; } async waitForElement(locator: Locator): Promise<void> { await locator.waitFor({ state: 'visible' }); } async clickElement(locator: Locator): Promise<void> { await this.waitForElement(locator); await locator.click(); } async fillElement(locator: Locator, text: string): Promise<void> { await this.waitForElement(locator); await locator.fill(text); } async navigateTo(url: string): Promise<void> { await this.page.goto(url); } }
再编写业务页面类,比如LoginPage(继承BasePage):
import { Page } from '@playwright/test'; import { BasePage } from './basePage'; export class LoginPage extends BasePage { // 页面元素定位 private readonly usernameInput = this.page.locator('#username'); private readonly passwordInput = this.page.locator('#password'); private readonly loginButton = this.page.locator('button[type="submit"]'); constructor(page: Page) { super(page); } // 封装页面操作 async login(username: string, password: string): Promise<void> { await this.fillElement(this.usernameInput, username); await this.fillElement(this.passwordInput, password); await this.clickElement(this.loginButton); } async navigateToLoginPage(): Promise<void> { await this.navigateTo('/login'); } }
4. 编写Feature文件
用Gherkin语法描述测试场景(features/auth/login.feature):
Feature: User Login Functionality As a user I want to log into the application So that I can access the dashboard Scenario: Successful login with valid credentials Given I am on the login page When I enter valid username and password And I click the login button Then I should be redirected to the dashboard Scenario Outline: Failed login with invalid credentials Given I am on the login page When I enter username "<username>" and password "<password>" And I click the login button Then I should see error message "<errorMsg>" Examples: | username | password | errorMsg | | wrong_user | wrong_pass | Invalid username or password | | test_user | wrong_pass | Invalid username or password |
5. 编写步骤定义
对应Feature中的Gherkin语句,串联POM操作(src/step-definitions/authSteps.ts):
import { Given, When, Then } from '@cucumber/cucumber'; import { LoginPage } from '../pages/loginPage'; import { DashboardPage } from '../pages/dashboardPage'; import { getAuthData } from '../utils/testDataUtils'; let loginPage: LoginPage; let dashboardPage: DashboardPage; Given('I am on the login page', async function () { loginPage = new LoginPage(this.page); // 通过this获取Playwright Page实例 await loginPage.navigateToLoginPage(); }); When('I enter valid username and password', async function () { const validUser = getAuthData('validUser'); await loginPage.login(validUser.username, validUser.password); }); When('I enter username {string} and password {string}', async function (username, password) { await loginPage.login(username, password); }); When('I click the login button', async function () { await loginPage.clickElement(loginPage['loginButton']); }); Then('I should be redirected to the dashboard', async function () { dashboardPage = new DashboardPage(this.page); await dashboardPage.waitForElement(dashboardPage['dashboardHeader']); }); Then('I should see error message {string}', async function (errorMsg) { await this.page.locator(`text=${errorMsg}`).waitFor(); });
6. 配置测试运行命令
在package.json中添加脚本:
"scripts": { "test": "cucumber-js --config src/cucumber.conf.ts", "test:headed": "cucumber-js --config src/cucumber.conf.ts --headed", // 可视化运行 "test:report": "cucumber-js --config src/cucumber.conf.ts --format html:cucumber-report.html" }
三、Feature与步骤定义的集成规则
- 步骤定义通过
Given/When/Then装饰器匹配Feature中的Gherkin语句,支持精确字符串匹配或正则匹配 - Cucumber会自动扫描
cucumber.conf.ts中require字段指定目录下的步骤定义文件,自动关联Feature中的步骤 - 步骤定义中的
this.page是Playwright与Cucumber集成后注入的全局Page实例,无需手动创建
四、步骤定义中运用POM实现复用与维护
- 所有页面元素定位和操作都封装在POM页面类中,步骤定义只做流程串联,不写具体DOM操作
- 当页面元素或交互逻辑变更时,仅需修改对应的POM页面类,无需改动步骤定义和Feature文件
- 通用操作(如等待元素、点击、输入)统一封装在BasePage中,所有业务页面类继承BasePage实现复用
五、测试数据的使用与维护
1. 测试数据存储
按业务模块分类存储在JSON文件中(src/test-data/authData.json):
{ "validUser": { "username": "test_user", "password": "test_pass123" }, "lockedUser": { "username": "locked_user", "password": "locked_pass" } }
2. 测试数据读取
编写工具类统一读取数据(src/utils/testDataUtils.ts):
import * as fs from 'fs'; import * as path from 'path'; export function getAuthData(userType: string): any { const filePath = path.join(__dirname, '../test-data/authData.json'); const rawData = fs.readFileSync(filePath, 'utf-8'); return JSON.parse(rawData)[userType]; }
3. 维护规则
- 测试数据与代码分离,新增/修改数据无需改动业务代码
- 敏感数据可通过环境变量注入,避免硬编码在JSON文件中
- 复杂场景可结合Feature的
Scenario Outline+Examples表格管理多组测试数据
内容的提问来源于stack exchange,提问作者Jagruti
相关产品推荐
相关产品推荐

