You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Playwright中每次执行测试时清理浏览器会话?

如何在Playwright中每次执行测试时清理浏览器会话?

嗨,我完全懂你遇到的困扰——Playwright的会话隔离逻辑和Cypress不太一样,导致重复跑测试时总会残留之前的登录状态,确实挺闹心的。咱们来一步步把这个问题解决掉:

首先得先理清楚Playwright里browsercontextpage这三个核心概念的关系,这是解决问题的关键:

  • browser是整个浏览器实例,启动后默认不会自动销毁
  • context相当于浏览器的隐私窗口,每个上下文之间的Cookie、本地存储是完全隔离的,互不干扰
  • page是上下文里的标签页,同一个上下文里的所有页面都会共享会话状态

你之前尝试的代码里,用browser.newPage()只是在同一个浏览器实例里创建新标签页,但没有创建新的context,所以页面还是会复用之前的会话,这就是为什么Roles测试能直接访问需要登录的页面——它和前面的测试共用了同一个上下文。

正确的解决办法:让每个测试拥有独立的上下文

Playwright Test框架其实默认就支持为每个测试创建全新的上下文,你完全不用手动去折腾browserpage的创建,只要用好测试函数里的参数就行。

方法一:直接用框架默认的隔离机制

Playwright Test会自动为每个测试分配一个全新的contextpage,你只需要直接使用测试函数里的page参数即可:

const { test, expect } = require("@playwright/test");
const { LoginPage } = require("../pages/LoginPage");

test("Login", async ({ page }) => {
  const loginPage = new LoginPage(page);
  await loginPage.userLogged(user, password);
  await page.goto(`${process.env.web_url}/users`);
});

test("Roles", async ({ page }) => {
  // 这里的page是全新上下文的页面,没有任何登录状态,所以访问需要登录的页面会失败,符合你的预期
  await page.goto(`${process.env.webapp_url}/roles`);
});

这样每次运行测试,都会拿到一个完全干净的环境,和你习惯的Cypress行为完全一致。

方法二:手动创建上下文(适合需要自定义配置的场景)

如果你需要给上下文加一些自定义配置(比如固定视口、设置权限等),可以用test.beforeEach在每个测试前创建全新的上下文和页面:

const { test, expect } = require("@playwright/test");
const { LoginPage } = require("../pages/LoginPage");

let page;
let context;

test.beforeEach(async ({ browser }) => {
  // 每个测试前都创建一个全新的上下文
  context = await browser.newContext({
    // 这里可以加自定义配置,比如viewport: { width: 1280, height: 720 }
  });
  page = await context.newPage();
});

test("Login", async () => {
  const loginPage = new LoginPage(page);
  await loginPage.userLogged(user, password);
  await page.goto(`${process.env.web_url}/users`);
});

test("Roles", async () => {
  // 这个page属于全新上下文,没有之前的登录状态
  await page.goto(`${process.env.webapp_url}/roles`);
});

test.afterEach(async () => {
  // 每个测试结束后关闭上下文,彻底清理状态
  await context.close();
});

额外小技巧:复用登录状态(如果需要加速测试)

如果之后你想优化测试速度,不想每次都重复登录,也可以用context.storageState()保存会话状态,在其他测试里直接加载:

// 先运行一次登录测试,保存会话状态
test("Save login state", async ({ page }) => {
  const loginPage = new LoginPage(page);
  await loginPage.userLogged(user, password);
  // 把会话状态保存到文件
  await page.context().storageState({ path: "playwright/.auth/user.json" });
});

// 让其他测试复用保存的会话状态
test.use({ storageState: "playwright/.auth/user.json" });

test("Roles with saved session", async ({ page }) => {
  await page.goto(`${process.env.webapp_url}/roles`);
  // 这里已经处于登录状态,不需要再执行登录步骤
});

不过这是优化场景,你现在需要的是完全隔离,所以前面两种方法更贴合你的需求。

备注:内容来源于stack exchange,提问作者José Antonio

火山引擎 最新活动