Quiet
  • 主页
  • 归档
  • 分类
  • 标签
  • 链接
  • 关于我

bajiu

  • 主页
  • 归档
  • 分类
  • 标签
  • 链接
  • 关于我
Quiet主题
  • 前端工程化

前端 E2E 测试简介

bajiu
前端

2025-08-25 15:36:00

前端 E2E 测试(End-to-End Test,全流程端到端测试)指的是在真实用户使用的场景下,模拟用户在浏览器里对前端应用的操作,从而验证整个系统是否能按照预期工作。

与单元测试、集成测试的区别在于:

  • 单元测试(Unit Test):测试一个函数/组件是否正确工作。
  • 集成测试(Integration Test):测试几个模块组合在一起是否能正常运行。
  • E2E 测试:模拟一个真实用户从打开页面、点击按钮、输入内容、跳转页面,到后台 API 返回数据、页面渲染结果的全流程。

特点

  1. 运行环境接近真实用户体验

一般通过真实浏览器(Chrome/Firefox)或无头浏览器(Headless Chrome)运行,模拟点击、输入、滚动、截图等操作。

  1. 跨层验证

不仅验证前端页面,还会通过调用后端 API、数据库的响应来确保整个系统的链路没问题。

  1. 面向用户行为

关注的是 用户能不能完成一件事情,而不是内部代码实现。

常用工具

  • Cypress:现在最流行的 E2E 测试框架之一,支持实时调试、快照、断言直观。
  • Playwright:微软推出,支持多浏览器(Chromium、Firefox、WebKit),功能强大。
  • Puppeteer:Google 出品,控制 Chromium 的无头浏览器工具,偏向于自动化+测试。
  • Selenium:老牌 E2E 测试框架,支持多语言、多浏览器。

Playwright 基础

一、安装与初始化

# 在前端项目根目录
pnpm add -D @playwright/test
# 一键装浏览器
npx playwright install
# 可选:生成示例结构
npx playwright codegen https://www.summer889.com

推荐目录(monorepo 也通用):

.
├─ playwright.config.ts
├─ tests/
│  ├─ smoke/            # 冒烟用例
│  ├─ auth/             # 登录相关
│  ├─ features/         # 业务场景
│  └─ fixtures/         # 共享夹具
└─ e2e-assets/          # 测试数据、上传文件、下载落地等

package.json 脚本:

{
  "scripts": {
    "test:e2e": "playwright test",
    "test:e2e:ui": "playwright test --ui",
    "test:e2e:headed": "playwright test --headed",
    "test:e2e:debug": "PWDEBUG=1 playwright test",
    "test:e2e:report": "playwright show-report"
  }
}

二、基础配置(含 Vite 预览、一键起停)

playwright.config.ts

import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
  testDir: './tests',
  timeout: 30_000,
  expect: { timeout: 5_000 },
  fullyParallel: true,
  retries: process.env.CI ? 2 : 0,
  reporter: [['html', { open: 'never' }], ['list']],
  use: {
    baseURL: process.env.BASE_URL || 'http://localhost:5173',
    trace: 'on-first-retry',       // 失败重试时录制 trace
    screenshot: 'only-on-failure',
    video: 'retain-on-failure',
    actionTimeout: 10_000,
    navigationTimeout: 15_000,
  },
  // 让 Playwright 帮你启/停本地 Vite 预览(或 Next/Express)
  webServer: {
    command: 'pnpm run preview',   // 例如 vite preview
    url: 'http://localhost:5173',
    reuseExistingServer: !process.env.CI,
    timeout: 120_000,
  },
  projects: [
    { name: 'chromium', use: { ...devices['Desktop Chrome'] } },
    { name: 'firefox',  use: { ...devices['Desktop Firefox'] } },
    { name: 'webkit',   use: { ...devices['Desktop Safari'] } },
    // 可选移动端视口
    // { name: 'Mobile Chrome', use: { ...devices['Pixel 7'] } },
  ],
});

如果 Vite:确保有 pnpm run preview 脚本(vite preview)

三、选择器与可测性约定

建议用 data-testid 或 data-test 做稳定选择器,避免 class/文本波动:

<button data-testid="login-submit">登录</button>
<input data-testid="email" />

Playwright 用法:

await page.getByTestId('email').fill('user@163.com');
await page.getByTestId('login-submit').click();

四、用例:

登录(存储态复用)

  1. 首次登录并保存 storageState:

tests/auth/login.setup.spec.ts

import { test, expect } from '@playwright/test';

test('setup: login and save state', async ({ page }) => {
  await page.goto('/login');
  await page.getByTestId('email').fill('e2e@demo.com');
  await page.getByTestId('password').fill('P@ssw0rd!');
  await page.getByTestId('login-submit').click();
  await expect(page).toHaveURL(/dashboard/);
  // 保存登录态,后续用例复用,避免每次都走登录流程
  await page.context().storageState({ path: 'tests/fixtures/authState.json' });
});
  1. 在业务用例里复用登录态:

playwright.config.ts 增加一个带 storageState 的 project 或在用例中指定:

// 在某个项目里开启
{ 
    name: 'chromium-auth', 
    use: { 
            ...devices['Desktop Chrome'], 
            storageState: 'tests/fixtures/authState.json' 
        } 
}

或在单测里:

test.use({ storageState: 'tests/fixtures/authState.json' });

test('已登录访问订单页', async ({ page }) => {
  await page.goto('/orders');
  await page.getByRole('heading', { name: '我的订单' }).isVisible();
});

网络拦截

test('搜索接口 mock', async ({ page }) => {
  await page.route('**/api/search**', async route => {
    const url = route.request().url();
    if (url.includes('q=手机')) {
      return route.fulfill({
        status: 200,
        contentType: 'application/json',
        body: JSON.stringify({ items: [{ id: 1, name: 'Playwright Phone' }] })
      });
    }
    return route.continue();
  });

  await page.goto('/');
  await page.getByPlaceholder('搜索').fill('手机');
  await page.keyboard.press('Enter');

  await expect(page.getByText('Playwright Phone')).toBeVisible();
});

Electron 应用

Playwright 支持 Electron:

import { _electron as electron, test, expect } from '@playwright/test';

test('electron smoke', async () => {
  const app = await electron.launch({ args: ['.'] }); // 你的 electron 主进程入口
  const win = await app.firstWindow();
  await win.waitForLoadState('domcontentloaded');
  await expect(win.getByText('欢迎')).toBeVisible();
  await app.close();
});

若前端由 Vite 提供页面,仍可用 webServer 起预览,再由 Electron 加载;E2E 可分两层:Web(浏览器)和 Electron(壳)。

五、测试报告

用 Playwright 生成 / 查看测试报告主要有 3 种常用方式:HTML 报告、JUnit/JSON 等机器可读报告、以及 Trace/Screenshot/Video 附件。

  1. HTML 报告(最常用)

配置(推荐放在 playwright.config.ts)

import { defineConfig } from '@playwright/test';

export default defineConfig({
  reporter: [
    ['html', { open: 'never', outputFolder: 'playwright-report' }],
    // 可选:还想要控制台 list 报告
    ['list']
  ],
  use: {
    trace: 'on-first-retry',          // 失败重试时会录制 trace
    screenshot: 'only-on-failure',
    video: 'retain-on-failure',
  },
});

运行生成报告

pnpm test:e2e             # 或 npx playwright test

本地查看报告

pnpm test:e2e:report      # 等价于 npx playwright show-report
# 或指定目录:
npx playwright show-report playwright-report

打开的是一个可交互的网页:能按用例筛选、看重试历史、点进单测查看步骤与附件(截图/视频/trace)。

一键脚本(建议加到 package.json)

{
  "scripts": {
    "test:e2e": "playwright test",
    "test:e2e:ui": "playwright test --ui",
    "test:e2e:report": "playwright show-report", 
    "test:e2e:trace": "playwright show-trace test-results/**/trace.zip"
  }
}
下一篇

U2Netp WebGL 实时抠像

©2025 By bajiu.