Playwright Test
Playwright, además de ser una herramienta de automatización de navegadores, incluye unframework de pruebas completo —— Playwright Test。
Playwright Test nos ayuda a organizar casos de prueba, generar informes, ejecutar en paralelo y reintentar fallos; es completo y listo para usar.
- Playwright Test es unframework de pruebas integrado, sin dependencias adicionales.
- El archivo de configuración puede establecertiempos de espera, reintentos, informes, proyectos de navegadoretc.
- Los casos de prueba admitenagrupación, hooks, data-driven。
- Ofreceejecución paralela, informes HTML, reintentos de fallosy otras capacidades avanzadas.
Resumen del framework de pruebas
- Framework de pruebas integrado: incluye su propio runner de pruebas, sin necesidad de instalar Jest, Mocha.
- Librería de aserciones integrada: admite
expectaserciones. - Aislamiento de pruebas: cada
testse ejecuta por defecto en un nuevo contexto de navegador, sin interferirse entre sí. - Funciones enriquecidas: ejecución paralela, reintentos, capturas de pantalla, grabación, informes HTML, etc.
Instalación:
npm init playwright@latest
Genera automáticamente la estructura del proyecto, incluido el archivo de configuraciónplaywright.config.js。
1. Detalles del archivo de configuración
Playwright Test utilizaplaywright.config.js(o.ts) como punto de entrada de configuración.
// playwright.config.js
import { defineConfig } from '@playwright/test';
export default defineConfig({
testDir: './tests', // 测试目录
timeout: 30 * 1000, // 单个测试超时时间
retries: 2, // 失败重试次数
reporter: [['html'], ['list']], // 测试报告类型
use: {
headless: true, // 是否无头模式
screenshot: 'only-on-failure', // 失败时截图
video: 'retain-on-failure', // 失败时保留视频
baseURL: 'https://example.com', // 基础 URL
},
projects: [
{ name: 'Chromium', use: { browserName: 'chromium' } },
{ name: 'Firefox', use: { browserName: 'firefox' } },
{ name: 'WebKit', use: { browserName: 'webkit' } },
],
});
2. Estructura del script de pruebas
Los scripts de Playwright Test normalmente incluyen:
1. Importar la librería de pruebas
import { test, expect } from '@playwright/test';
2. Escribir casos de prueba
test('示例测试', async ({ page }) => {
await page.goto('https://example.com');
await expect(page).toHaveTitle('Example Domain');
});
3. Agrupación y hooks
- Usar
describeorganizar pruebas - Usar
beforeEach/afterEachpara el manejo de preparación y limpieza
Escribir casos de prueba
1. test()Uso de funciones
test('页面标题验证', async ({ page }) => {
await page.goto('https://playwright.dev');
await expect(page).toHaveTitle(/Playwright/);
});
2. describe()Agrupación
test.describe('用户登录模块', () => {
test('输入正确账号密码', async ({ page }) => {
// 登录逻辑...
});
test('输入错误密码', async ({ page }) => {
// 验证错误提示...
});
});
3. Hooks de prueba
test.describe('购物车模块', () => {
test.beforeEach(async ({ page }) => {
await page.goto('https://example.com/cart');
});
test.afterEach(async ({ page }) => {
await page.screenshot({ path: 'cart.png' });
});
test('添加商品', async ({ page }) => {
await page.click('#add-item');
await expect(page.locator('#cart-count')).toHaveText('1');
});
});
4. Preparación de datos de prueba
Admite pruebas parametrizadas:
const users = [
{ name: 'admin', password: '123456' },
{ name: 'guest', password: 'guest' },
];
for (const user of users) {
test(`用户 ${user.name} 登录`, async ({ page }) => {
await page.goto('https://example.com/login');
await page.fill('#username', user.name);
await page.fill('#password', user.password);
await page.click('#submit');
await expect(page.locator('.welcome')).toBeVisible();
});
}
Ejecución e informes
1. Comandos de ejecución de pruebas
npx playwright test # 运行全部测试 npx playwright test login.spec.js # 运行单个文件 npx playwright test -g "登录" # 运行指定用例
2. Pruebas en paralelo
Playwright por defectoejecuta en paralelo por archivo, también se puede especificar el número de workers en el archivo de configuración:
npx playwright test --workers=4
3. Generación de informes de pruebas
Después de la ejecución se generainforme HTML:
npx playwright show-report
4. Mecanismo de reintento en caso de fallo
En el archivo de configuraciónplaywright.config.jsse establece:
retries: 2
Cuando una prueba falla, se reintenta automáticamente, adecuado para manejar errores esporádicos.
- Playwright Test es unframework de pruebas integrado, sin dependencias adicionales.
- El archivo de configuración puede establecertiempos de espera, reintentos, informes, proyectos de navegadoretc.
- Los casos de prueba admitenagrupación, hooks, data-driven。
- Proporcionaejecución paralela, informes HTML, reintentos de fallosy otras capacidades avanzadas.
Ejemplo de suite de pruebas completa
1. Estructura del proyecto
playwright-demo/ ├─ playwright.config.ts # 全局配置(多项目、多浏览器、报告、重试…) ├─ package.json ├─ tests/ │ ├─ auth.setup.ts # 一次性登录,生成 storageState │ ├─ smoke/ │ │ └─ home.spec.ts # 冒烟用例:标题/URL/截图对比 │ └─ e2e/ │ └─ cart.spec.ts # 端到端:添加购物车、断言、附件、步骤 ├─ fixtures/ │ ├─ pages.ts # 页面对象(PO) │ └─ test.extend.ts # 自定义 fixtures └─ snapshots/ # 视觉基线(自动生成)
2. Archivo de configuración (playwright.config.ts)
Ejemplo
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
testDir: './tests',
timeout: 30_000,
retries: 2,
workers: 4,
reporter: [['html', { outputFolder: 'report' }], ['list']],
forbidOnly: !!process.env.CI,
// Uso predeterminado unificado (se puede sobrescribir a nivel de proyecto o de prueba)
use: {
baseURL: 'https://demo.playwright.dev',
headless: true,
screenshot: 'only-on-failure',
video: 'retain-on-failure',
trace: 'retain-on-failure',
viewport: { width: 1366, height: 900 },
locale: 'zh-CN',
},
// Múltiples proyectos: diferentes navegadores/dispositivos/estados de sesión
projects: [
{ name: 'Chromium', use: { ...devices['Desktop Chrome'] } },
{ name: 'Firefox', use: { ...devices['Desktop Firefox'] } },
{
name: 'Mobile Chrome',
use: { ...devices['Pixel 7'], headless: true },
},
// Proyecto con estado de sesión (reutiliza storageState)
{
name: 'Chromium Logged-in',
use: { storageState: 'storageState.json' },
dependencies: ['setup'], // Depende del proyecto previo para generar el estado de sesión
},
// Proyecto previo "setup": se ejecuta una sola vez para generar storageState
{
name: 'setup',
testMatch: /auth\.setup\.ts/,
},
],
});
Puntos clave:projects permite que el mismo conjunto de casos se ejecute en diferentes navegadores/configuraciones; use puede sobrescribirse a nivel global, de proyecto o de prueba; los informes y reintentos se gestionan de forma centralizada en la configuración.
3. Fixtures y objetos de página
fixtures/test.extend.ts (fixture personalizado + encapsulación de pasos comunes)
Ejemplo
import { test as base } from '@playwright/test';
import { HomePage, CartPage } from './pages';
type MyFixtures = {
home: HomePage;
cart: CartPage;
};
export const test = base.extend<MyFixtures>({
home: async ({ page }, use) => {
const home = new HomePage(page);
await use(home);
},
cart: async ({ page }, use) => {
const cart = new CartPage(page);
await use(cart);
},
});
export { expect } from '@playwright/test';
Usando test.extend() se añaden fixtures personalizados, lo que permite inyectar directamente las instancias home y cart en cualquier caso de prueba.
fixtures/pages.ts (objetos de página)
Ejemplo
import { Page, expect } from '@playwright/test';
export class HomePage {
constructor(private page: Page) {}
async goto() { await this.page.goto('/'); }
get tryTodoLink() { return this.page.getByRole('link', { name: /ToDo MVC/i }); }
}
export class CartPage {
constructor(private page: Page) {}
async goto() { await this.page.goto('/e2e'); } // Suponiendo que existe una página de ejemplo e2e
get addFirstItem() { return this.page.getByRole('button', { name: /Add .* #1/i }); }
get cartCount() { return this.page.locator('[data-test=cart-count]'); }
async addOne() { await this.addFirstItem.click(); }
async expectCount(n: number) { await expect(this.cartCount).toHaveText(String(n)); }
}
4. Inicio de sesión previo (generación única de storageState)
tests/auth.setup.ts (se ejecuta solo en el proyecto "setup")
Ejemplo
import { test, expect } from '@playwright/test';
test('create storageState', async ({ page }) => {
await page.goto('https://demo.playwright.dev/todomvc');
// ... reemplaza aquí por tu flujo de inicio de sesión ...
// Suponiendo que el inicio de sesión fue exitoso
await expect(page).toHaveURL(/todomvc/);
await page.context().storageState({ path: 'storageState.json' });
});
5. Smoke tests (título/URL/comparación visual)
tests/smoke/home.spec.ts
Ejemplo
test.describe('Smoke - Home', () => {
test('title & url & visual snapshot', async ({ page }) => {
await page.goto('https://playwright.dev');
await expect(page).toHaveTitle(/Playwright/);
await expect(page).toHaveURL(/playwright\.dev/);
// Regresión visual (generación/comparación automática de línea base)
await expect(page).toHaveScreenshot(); // La primera ejecución generará la línea base
});
});
Para la comparación visual se recomienda usar toHaveScreenshot (en lugar del enfoque manual con page.screenshot() + toMatchSnapshot).
6. Pruebas de extremo a extremo (pasos, adjuntos, aserciones)
tests/e2e/cart.spec.ts
Ejemplo
test.describe.configure({ mode: 'parallel' });
test.describe('E2E - Cart', () => {
test.beforeEach(async ({ home }) => {
await test.step('Ir a la página de inicio', async () => {
await home.goto();
});
});
test('Añadir producto al carrito (con adjuntos y aserciones)', async ({ page, cart }) => {
await test.step('Ir a la página del carrito y añadir el producto', async () => {
await cart.goto();
await cart.addOne();
await cart.expectCount(1);
});
await test.step('Adjuntar información de depuración al informe', async () => {
await test.info().attach('state.json', {
contentType: 'application/json',
body: Buffer.from(JSON.stringify({ ts: Date.now(), note: 'after add' })),
});
});
// Captura de pantalla a nivel de elemento
await test.step('Captura de pantalla del elemento', async () => {
const badge = page.locator('[data-test=cart-count]');
await expect(badge).toBeVisible();
await expect(badge).toHaveScreenshot(); // Snapshot del elemento
});
});
});
Usa test.step para registrar pasos de forma jerárquica, usa test.info().attach() para adjuntar datos de depuración/capturas al informe, lo que facilita la depuración; en modo paralelo se puede usar describe.configure({ mode: 'parallel' }).
7. Ejecución e informes
Comandos comunes:
npx playwright test # 运行全部 npx playwright test tests/e2e # 运行目录 npx playwright test -g "Cart" # 按标题过滤 npx playwright test --project="Chromium" # 指定项目 npx playwright show-report # 打开HTML报告 npx playwright test --update-snapshots # 更新视觉基线 npx playwright test --debug # 调试模式(Inspector)
Para el filtrado por CLI, selección de proyectos, visualización de informes y actualización de snapshots, consulte la documentación oficial de CLI/informes/snapshots.
Referencia rápida de API relacionadas comunes (Playwright Test)
1. Pruebas y agrupación
| API | Descripción |
|---|---|
test(name, fn) |
Definir pruebas |
test.describe(title, fn) |
Agrupación |
test.describe.configure({ mode }) |
parallel / serial |
test.beforeAll/afterAll |
Preparación y limpieza a nivel de grupo |
test.beforeEach/afterEach |
Preparación y limpieza a nivel de caso |
test.skip/only/fixme/slow/fail |
Marcar/controlar casos |
2. Fixtures y configuración
| API | Descripción |
|---|---|
test.extend<Fixtures>(defs) |
Extender fixtures personalizados |
test.use(options) |
Sobrescritura a nivel de pruebauseOpciones (comostorageState、viewport、localeetc.) |
defineConfig({...}) |
Punto de entrada de configuración (testDir、retries、workers、reporter…) |
projects |
ejecución con múltiples proyectos/navegadores/configuraciones diferentes |
use: { baseURL, trace, video, screenshot, viewport, locale, timezoneId, storageState } |
) |
Entorno de ejecución y estrategias de capturaPlaywright)
3. Aserciones (expect)
| API | Descripción | |
|---|---|---|
expect(value).toBe / toEqual / toContain ... |
Aserciones generales | |
expect(locator).toHaveText/Value/Attribute |
Aserciones específicas de Web (con espera inteligente) | |
expect(locator).toBeVisible/Hidden/Enabled/Disabled/Checked |
Aserción de estado | |
expect(page).toHaveTitle/URL |
Aserción de página | |
| `expect(page/locator).toHaveScreenshot([name | options])` | Comparación de instantáneas visuales (recomendado) |
Las prácticas recomendadas para aserciones e instantáneas visuales se detallan en la documentación de Assertions y Snapshots. (Playwright)
4. Pasos y adjuntos
| API | Función | |
|---|---|---|
test.step(name, fn) |
Dividir la prueba en pasos (visualización en el informe) | |
| `test.info().attach(name, { path | body, contentType })` | Adjuntar archivos/datos a la prueba o al paso (se muestran en el informe) |
Los adjuntos también pueden aplicarse a nivel de paso (consulte TestStep / TestStepInfo). (Playwright)
5. Informes y CLI
| Comando/Configuración | Función |
|---|---|
reporter: [['html', { outputFolder }], ['list']] |
Configuración del informe |
npx playwright test --project="Chromium" |
Seleccionar proyecto para ejecutar |
-g "keyword" / --grep / --grep-invert |
Filtrar casos de uso |
--update-snapshots |
Actualizar la línea base visual |
npx playwright show-report |
Abrir informe |
Otras extensionesConsulte la documentación oficial para ver las opciones completas de CLI y Reporter. (Playwright)