无法在Behave步骤文件中集成Playwright,遇事件循环关闭错误
解决Behave+Playwright中浏览器秒开秒关及事件循环关闭问题
问题现象
执行Behave步骤文件时,浏览器秒开秒关无实际操作,抛出错误:
Error: raise Error("Event loop is closed! Is Playwright already stopped?") playwright._impl._errors.Error: Event loop is closed! Is Playwright already stopped? When the user enters a valid username. # None And the user logs out from the application. # None
原代码示例
from behave import * from playwright.sync_api import sync_playwright # Initialize playwright outside step definitions with sync_playwright() as p: browser = p.chromium.launch(headless=False, slow_mo=800) page = browser.new_page() @given(u'the user is on Pilot server login page.') def step_impl(context): page.goto("https://playwright.dev/") @when(u'the user enters a valid username.') def step_impl(context): button_by_role = page.get_by_role('link', name="Docs") button_by_role.click() @when(u'the user logs out from the application.') def step_impl(context): page.screenshot(path="features/Screenshots/demo.png") # Taking screenshot for the proof
问题根源
sync_playwright()的with语句会在代码块执行完毕后自动关闭Playwright实例和对应的事件循环。原代码中初始化逻辑放在with块内,程序加载阶段执行完with块就直接销毁了Playwright实例,后续执行步骤时调用的page已失效,导致浏览器秒关并抛出事件循环关闭的错误。
解决方案
使用Behave的钩子函数管理Playwright实例的生命周期,确保在测试全程实例有效,测试结束后正确清理资源。修改后的代码如下:
from behave import * from playwright.sync_api import sync_playwright # 全局变量存储Playwright相关实例 p = None browser = None page = None def before_all(context): """所有测试步骤执行前初始化Playwright、浏览器和页面""" global p, browser, page p = sync_playwright().start() browser = p.chromium.launch(headless=False, slow_mo=800) page = browser.new_page() def after_all(context): """所有测试步骤执行完成后清理资源""" global p, browser, page page.close() browser.close() p.stop() @given(u'the user is on Pilot server login page.') def step_impl(context): page.goto("https://playwright.dev/") @when(u'the user enters a valid username.') def step_impl(context): button_by_role = page.get_by_role('link', name="Docs") button_by_role.click() @when(u'the user logs out from the application.') def step_impl(context): page.screenshot(path="features/Screenshots/demo.png")
修改说明
- 通过
before_all钩子在测试开始前启动Playwright、浏览器和页面,保证实例在整个测试周期内可用。 - 通过
after_all钩子在测试结束后依次关闭页面、浏览器并停止Playwright,正确释放资源,避免内存泄漏。 - 移除原有的
with块,避免Playwright实例被提前销毁。
内容的提问来源于stack exchange,提问作者AbdulRehman Rizwan
相关产品推荐
相关产品推荐

