现在位置: 首页 > Playwright 教程 > 正文

Playwright 认证(Authentication)

本章介绍如何在 Playwright 中处理认证,避免每个测试都重复登录,同时保持测试的隔离性。


认证的核心问题

大多数 Web 应用的测试都需要用户登录。

如果每个测试都从头执行登录流程,会显著拖慢测试速度。

Playwright 的解决方案是:认证一次,保存状态,所有测试复用


准备工作:.auth 目录

实例

# 创建认证状态存储目录
mkdir -p playwright/.auth

# 添加到 .gitignore(认证状态包含机密信息)
echo 'playwright/.auth' >> .gitignore

.auth 文件包含敏感 Cookie 和认证 Token,绝对不能提交到代码仓库


基本方案:共享账号 + Setup 项目

这是 Playwright 推荐的认证方案,适用于所有测试共享同一个测试账号的场景。

第一步:创建认证 Setup

实例

// 文件路径:tests/auth.setup.ts
import { test as setup } from '@playwright/test';

// 指定认证状态保存路径
const authFile = 'playwright/.auth/user.json';

setup('authenticate', async ({ page }) => {
  // 执行登录操作
  await page.goto('https://www.runoob.com/login');
  await page.getByLabel('用户名').fill('testuser');
  await page.getByLabel('密码').fill('password123');
  await page.getByRole('button', { name: '登录' }).click();

  // 等待登录完成(确认页面跳转或出现用户信息)
  await page.waitForURL(/dashboard/);

  // 将当前的认证状态(Cookie、localStorage)保存到文件
  await page.context().storageState({ path: authFile });
});

第二步:配置 Setup 项目

实例

// 文件路径:playwright.config.ts
import { defineConfig } from '@playwright/test';

export default defineConfig({
  projects: [
    // Setup 项目 —— 只运行一次,生成认证状态文件
    {
      name: 'setup',
      testMatch: /auth\.setup\.ts/,
    },

    // 实际测试项目 —— 复用认证状态
    {
      name: 'chromium',
      use: {
        storageState: 'playwright/.auth/user.json',
      },
      dependencies: ['setup'],    // 依赖 setup 项目,确保 setup 先运行
    },
  ],
});

第三步:测试直接使用认证状态

实例

// 文件路径:tests/dashboard.spec.ts
import { test, expect } from '@playwright/test';

test('查看仪表盘', async ({ page }) => {
  // 直接访问需要登录的页面,page 已经带着认证状态
  await page.goto('/dashboard');
  await expect(page.getByText('欢迎回来,testuser')).toBeVisible();
});

多账号场景

如果不同测试需要使用不同账号,可以创建多个认证状态文件。

实例

// 管理员测试
test.describe('管理员功能', () => {
  test.use({ storageState: 'playwright/.auth/admin.json' });

  test('管理用户', async ({ page }) => {
    // 以管理员身份操作
  });
});

// 普通用户测试
test.describe('普通用户功能', () => {
  test.use({ storageState: 'playwright/.auth/user.json' });

  test('浏览内容', async ({ page }) => {
    // 以普通用户身份操作
  });
});

通过 API 请求认证(推荐)

通过 UI 执行登录流程较慢,更高效的方式是直接调用登录 API。

实例

// 文件路径:tests/auth.setup.ts
import { test as setup } from '@playwright/test';

const authFile = 'playwright/.auth/user.json';

setup('通过 API 认证', async ({ request }) => {
  // 直接调用登录 API,不通过浏览器 UI
  const response = await request.post('https://www.runoob.com/api/login', {
    data: {
      username: 'testuser',
      password: 'password123',
    },
  });

  // 确认登录成功
  const json = await response.json();
  console.log('登录成功,Token:', json.token);

  // 将 Token 保存为 Cookie(模拟浏览器认证状态)
  // 注意:storageState 需要在浏览器 Context 中保存
});

API 认证比 UI 认证更快更可靠,推荐在实际项目中优先使用。


认证方案的适用场景总结

场景推荐方案
所有测试用同一个测试账号Setup 项目 + storageState
不同类型测试需要不同账号多个 storageState + test.use
每个测试需要独立账号每个测试内 API 创建账号并登录
账号资源有限Setup 项目认证一次,全部复用