如何在Playwright(TypeScript)中结合上下文实现页面对象模型?
问题分析与解决方案
错误根源
核心问题是测试代码未等待异步的goto()方法执行完成:当调用devPage.goto()却不加await时,测试会直接结束,Playwright会自动关闭浏览器实例;但此时goto()内部的异步逻辑仍在运行,尝试调用已关闭的浏览器创建上下文,就会抛出browser.newContext: Browser has been closed错误。
此外,当前AppPage的设计存在不合理性:每次调用goto()都会新建上下文和页面,既浪费资源,也不符合页面对象模型的状态管理预期。
修正后的实现方案
基础修复:补上异步等待
先解决直接报错问题,确保测试等待goto()完成:
test('test using context with page object model', async ({ browser }) => { const devPage = new AppPage(browser); await devPage.goto(); // 必须添加await });
优化页面对象设计(避免重复创建上下文)
将上下文和页面的初始化逻辑移到单独方法,确保每个AppPage实例对应唯一的上下文和页面:
export class AppPage { readonly browser: Browser; private context?: BrowserContext; private page?: Page; constructor(browser: Browser) { this.browser = browser; } // 初始化上下文和页面 async setup() { this.context = await this.browser.newContext({ // 可在此添加storageState等配置 // storageState: './auth.json', }); this.page = await this.context.newPage(); } async goto() { if (!this.page) throw new Error('请先调用setup()初始化页面'); await this.page.goto('https://playwright.dev'); } // 测试结束后清理资源 async teardown() { await this.context?.close(); } }
对应测试代码
test('test using context with page object model', async ({ browser }) => { const devPage = new AppPage(browser); await devPage.setup(); await devPage.goto(); await devPage.teardown(); });
更优雅的写法:利用测试钩子
如果多个测试需要复用上下文,可以用Playwright的测试钩子简化代码:
let appPage: AppPage; test.beforeEach(async ({ browser }) => { appPage = new AppPage(browser); await appPage.setup(); }); test.afterEach(async () => { await appPage.teardown(); }); test('test using context with page object model', async () => { await appPage.goto(); });
关键注意事项
- 异步操作必须等待:所有返回Promise的方法(包括自定义异步方法)都要加
await,否则会导致资源提前释放。 - 资源合理复用:上下文和页面应在实例初始化时创建一次,避免重复创建造成的性能损耗。
- 主动清理资源:测试结束后关闭上下文,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Tabares
相关产品推荐
相关产品推荐

