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

Playwright 测试隔离与 Browser Context

本章介绍 Playwright 的测试隔离机制和 Browser Context 的概念,这是保证测试稳定可靠的关键设计。


什么是测试隔离

测试隔离是指每个测试用例运行在完全独立的环境中,互不影响。

在 Playwright 中,每个测试自动获得一个独立的Browser Context(浏览器上下文)。


Browser Context 是什么

Browser Context 相当于一个全新的浏览器配置文件

创建一个 Context 就像打开一个全新的浏览器窗口,拥有自己的 Cookie、localStorage、sessionStorage,但开销极低(毫秒级)。

概念类比说明
Browser(浏览器实例)打开了一个浏览器程序开销大,一般整个测试运行只创建一次
Browser Context(浏览器上下文)浏览器中的独立配置文件开销小,每个测试一个
Page(标签页)浏览器中的一个标签页在 Context 中打开页面

每个测试中的 pagecontext 都是全新的,所以一个测试修改了 localStorage 或 Cookie,不会影响其他测试。


Context 隔离的内容

每个 Browser Context 之间完全隔离以下内容:

隔离项说明
Cookies每个 Context 有独立的 Cookie 存储
localStorage本地存储完全隔离
sessionStorage会话存储完全隔离
IndexedDB浏览器数据库隔离
缓存(Cache)HTTP 缓存隔离

实例

// 测试 A 设置了 Cookie
test('测试 A', async ({ page }) => {
  await page.goto('https://www.runoob.com/');

  // 设置 Cookie(仅在当前 Context 生效)
  await page.context().addCookies([{
    name: 'runoob_session',
    value: 'abc123',
    domain: 'www.runoob.com',
    path: '/',
  }]);

  // 后续操作使用该 Cookie
});

// 测试 B 收到一个全新的 Context,没有测试 A 设置的 Cookie
test('测试 B', async ({ page }) => {
  await page.goto('https://www.runoob.com/');

  // context().cookies() 返回空数组
  const cookies = await page.context().cookies();
  console.log(cookies); // []
});

context fixture 的使用

除了 page,测试函数还可以访问 context fixture 来进行 Context 级别的操作。

实例

test('使用 context fixture', async ({ context, page }) => {
  // 在 Context 级别设置权限
  await context.grantPermissions(['geolocation']);
  await context.setGeolocation({ latitude: 39.9, longitude: 116.4 });

  // 在 Context 级别拦截网络
  await context.route('**/*.{png,jpg,jpeg}', route => route.abort());

  // page 在同一个 context 中,继承了上述设置
  await page.goto('https://www.runoob.com/');
});

多 Context 场景

当你需要在同一个测试中模拟多个独立的用户时,可以手动创建 Context。

实例

test('两个用户独立操作', async ({ browser }) => {
  // 为两个用户创建独立的 Context
  const userAContext = await browser.newContext();
  const userBContext = await browser.newContext();

  // 两个用户的页面完全隔离
  const pageA = await userAContext.newPage();
  const pageB = await userBContext.newPage();

  await pageA.goto('https://www.runoob.com/login');
  await pageB.goto('https://www.runoob.com/login');

  // 用户 A 登录
  await pageA.getByLabel('用户名').fill('user_a');
  await pageA.getByLabel('密码').fill('password_a');
  await pageA.getByRole('button', { name: '登录' }).click();

  // 用户 B 登录(各自独立的 Cookie/Session,互不影响)
  await pageB.getByLabel('用户名').fill('user_b');
  await pageB.getByLabel('密码').fill('password_b');
  await pageB.getByRole('button', { name: '登录' }).click();

  // 清理
  await userAContext.close();
  await userBContext.close();
});

测试隔离的好处

1. 可重现性

每个测试从相同的初始状态开始,在任何顺序下运行结果一致。

2. 防止级联失败

测试 A 失败不会导致测试 B 也失败,每个测试都是独立可调试的。

3. 支持并行执行

因为测试完全独立,Playwright 可以安全地在多个 worker 中并行运行它们。

测试隔离是 Playwright 的默认行为,每个 test() 自动获得独立的 pagecontext,无需任何额外配置。