剧作家测试自动化框架
一个强大的、可用于生产的Playwright测试自动化框架,具有用于可靠浏览器测试的全面实用程序,如下所示 页面对象模型(POM) 设计模式 OOP原则.
🚀 特性
- 页面对象模型:符合OOP原则的干净、可维护的测试架构
- 智能元素查找:弹性元件位置的多种回退策略
- 综合录井:带有时间戳和日志级别的详细日志
- 截图捕捉:故障和关键步骤的自动截图
- 多浏览器支持:Chrome、Firefox、Safari和移动视口
- 并行执行:并行运行测试以加快执行速度
- 错误处理:优雅的错误处理,错误信息清晰
- 测试数据管理:集中测试数据和配置
- HTML报告:包含屏幕截图和视频的丰富HTML测试报告
- TypeScript:完全支持TypeScript,以提高代码质量
- 面向对象程序设计:封装、继承、抽象和多态
📁 项目结构
PlaywrightFramework Using MCP/
├── pages/ # Page Object Model (POM)
│ ├── BasePage.ts # Abstract base class
│ ├── LoginPage.ts # Login page object
│ ├── HomePage.ts # Home page object
│ └── index.ts # Page exports
├── tests/ # Test files
│ └── ddms-login.spec.ts # Example login test (POM pattern)
├── utils/ # Utility classes
│ ├── elementFinder.ts # Smart element finding
│ ├── logger.ts # Comprehensive logging
│ ├── screenshotHelper.ts # Screenshot management
│ ├── testHelper.ts # Base test helper
│ ├── testDataManager.ts # Test data management
│ └── index.ts # Utility exports
├── test-data/ # Test data files
├── logs/ # Test execution logs
├── test-results/ # Test results and artifacts
│ ├── html-report/ # HTML test reports
│ ├── screenshots/ # Screenshots
│ └── artifacts/ # Videos and traces
├── .env # Environment variables (not in git)
├── .env.example # Example environment variables
├── playwright.config.ts # Playwright configuration
├── tsconfig.json # TypeScript configuration
├── .eslintrc.json # ESLint configuration
├── .prettierrc # Prettier configuration
├── POM_GUIDE.md # Page Object Model guide
├── REFACTORING_SUMMARY.md # Refactoring details
└── package.json # Project dependencies🛠️ 设置
先决条件
- Node.js(v14或更高版本)
- npm或纱线
安装
- 克隆存储库
- 安装依赖项:
npm install- 安装Playwright浏览器:
npx playwright install- 配置环境变量:
cp .env.example .env
# Edit .env with your configuration🧪 运行测试
运行所有测试
npm test在头部模式下运行测试(请参阅浏览器)
npm run test:headed在UI模式下运行测试(交互式)
npm run test:ui在特定浏览器中运行测试
npm run test:chrome
npm run test:firefox
npm run test:webkit调试测试
npm run test:debug查看测试报告
npm run test:report📝 写作测试
页面对象模型(推荐)
框架如下 页面对象模型(POM) 干净、可维护的测试模式:
import { test, expect } from '@playwright/test';
import { LoginPage, HomePage } from '../pages';
import { TestDataManager } from '../utils';
test.describe('Login Tests', () => {
let loginPage: LoginPage;
let homePage: HomePage;
test.beforeEach(async ({ page }, testInfo) => {
// Initialize page objects
loginPage = new LoginPage(page, testInfo);
homePage = new HomePage(page, testInfo);
});
test('should login successfully', async () => {
// Arrange
const credentials = TestDataManager.getLoginCredentials('default');
// Act
await loginPage.navigate();
await loginPage.login(credentials.username, credentials.password);
// Assert
await homePage.verifyHomeIsVisible();
await homePage.verifyUserIsLoggedIn();
});
});创建新页面对象
// pages/MyPage.ts
import { BasePage } from './BasePage';
import type { Page, TestInfo } from '@playwright/test';
export class MyPage extends BasePage {
private selectors = {
myButton: { role: 'button', text: 'Click Me' },
myInput: { label: 'My Input' }
};
constructor(page: Page, testInfo: TestInfo) {
super(page, testInfo, 'https://example.com/mypage', 'My Page');
}
async isLoaded(): Promise {
await this.waitForElement(this.selectors.myButton);
}
async clickMyButton(): Promise {
await this.smartClick(this.selectors.myButton);
}
}📚 有关POM的详细指南,请参阅 POM_GUIDE.md
基本测试结构(直接实用程序)
如果您需要直接访问没有页面对象的实用程序:
import { test, expect } from '@playwright/test';
import { TestHelper, TestDataManager } from '../utils';
test.describe('My Test Suite', () => {
test('should perform action', async ({ page }, testInfo) => {
// Initialize test helper
const helper = new TestHelper(page, testInfo, 'My_Test_Name');
const logger = helper.getLogger();
const elementFinder = helper.getElementFinder();
// Get test data
const urls = TestDataManager.getUrls();
const credentials = TestDataManager.getLoginCredentials();
try {
logger.section('MY TEST');
// Step 1: Navigate
await helper.executeStep(1, 'Navigate to page', async () => {
await helper.navigateTo(urls.baseUrl);
});
// Step 2: Interact with elements
await helper.executeStep(2, 'Click button', async () => {
await elementFinder.smartClick(
{
role: { role: 'button', name: 'Submit' },
text: 'Submit',
css: 'button[type="submit"]',
},
{ description: 'Submit button' }
);
});
// Verify results
await helper.verifyTextPresent('Success');
logger.finish('PASSED');
} catch (error) {
logger.error(`Test failed: ${error}`);
logger.finish('FAILED');
throw error;
}
});
});智能元素查找
该框架提供了多种寻找要素的策略:
await elementFinder.smartClick(
{
role: { role: 'button', name: 'Login' }, // Best - semantic
text: 'Login', // Good - user-visible
label: 'Login Button', // Good - accessible
placeholder: 'Enter text', // For inputs
testId: 'login-btn', // Data-testid
css: 'button.login', // CSS selector
xpath: '//button[@id="login"]', // XPath
},
{
description: 'Login button',
timeout: 10000,
}
);使用测试数据
// Get credentials
const creds = TestDataManager.getLoginCredentials('default');
// Get URLs
const urls = TestDataManager.getUrls();
// Get timeouts
const timeouts = TestDataManager.getTimeouts();
// Generate test data
const email = TestDataManager.generateRandomEmail();
const randomString = TestDataManager.generateRandomString(10);
const date = TestDataManager.formatDate(new Date(), 'YYYY-MM-DD');🎯 框架功能
1.智能元素查找
- 多种回退策略
- 失败时自动重试
- 清除错误消息
- 支持所有剧作家定位器
2.综合测井
- 控制台和文件记录
- 颜色编码的日志级别
- 步进跟踪
- 所有操作的时间戳
3.截图管理
- 故障时自动截图
- 特定步骤的屏幕截图
- 特定元素截图
- 组织在测试结果文件夹中
4.错误处理
- 优雅的错误处理
- 详细的错误消息
- 错误截图
- 堆栈痕迹保存
5.测试数据管理
- 基于环境的配置
- 集中测试数据
- 数据生成器
- 类型安全数据结构
🔧 配置
环境变量(.env)
BASE_URL=https://your-app.com
TEST_USERNAME=testuser
TEST_PASSWORD=password123
SLOW_MO=0
HEADLESS=false
LOG_LEVEL=info剧作家配置(playwriter.config.ts)
- 超时:每次测试60秒
- 重试:失败时重试1次(CI上重试2次)
- 并行:完全并行执行
- 记者:HTML、JSON、JUnit、控制台
- 截图:失败时
- 视频:失败时
- 追踪:第一次重试时
📊 报告
测试结果以多种格式保存:
- HTML报告:
test-results/html-report/index.html - JSON报告:
test-results/test-results.json - JUnit XML:
test-results/junit.xml - 截图:
test-results/screenshots/ - 视频:
test-results/artifacts/ - 日志:
logs/
🎨 代码质量
代码检查
npm run lint # Check for issues
npm run lint:fix # Fix issues automatically格式化
npm run format # Format all files
npm run format:check # Check formatting📚 最佳实践
- 使用描述性测试名称:清楚地描述测试的作用
- 使用TestHelper:利用内置实用程序实现一致性
- 记录所有步骤:使用
executeStep()用于清晰的测试流程 - 优雅地处理错误:使用带有适当日志记录的try-catch
- 使用智能选择器:更喜欢角色和文本,而不是CSS/XPath
- 整理测试数据:将测试数据保存在TestDataManager中
- 截图:捕捉关键时刻和失败
- 编写可维护的测试:保持测试简单和专注
🐛 调试
- 以头部模式运行:查看浏览器正在做什么
npm run test:headed- 使用UI模式:交互式调试
npm run test:ui- 调试模式:逐步使用调试器
npm run test:debug- 检查日志:查看详细日志
logs/文件夹
- 查看屏幕截图:检查
test-results/screenshots/
- 查看HTML报告:请参阅完整的测试执行报告
npm run test:report🤝 贡献
- 遵循现有的代码结构
- 对所有新文件使用TypeScript
- 添加全面日志记录
- 包括错误处理
- 撰写描述性评论
- 提交前先运行linting
📄 许可证
国际学生中心
👤 作者
你的名字
🙏 致谢
- 优秀测试框架的编剧团队
- 微软的TypeScript和VS代码
