Java Cucumber Selenium场景中如何同时处理双浏览器双用户操作
解决Cucumber Selenium+PicoContainer同场景双浏览器并行问题
你的核心问题是PicoContainer默认采用单例注入,导致同一个场景内多次获取WebDriver时复用了同一个实例,无法同时启动两个独立浏览器。下面是具体的改造方案:
1. 自定义浏览器管理类
创建一个BrowserManager类,用于维护多个独立的WebDriver实例,按用户标识区分:
import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; import java.util.HashMap; import java.util.Map; public class BrowserManager { private final Map<String, WebDriver> driverMap = new HashMap<>(); public WebDriver getDriver(String userIdentifier) { if (!driverMap.containsKey(userIdentifier)) { // 初始化Chrome浏览器实例,可按需添加配置(如无头模式、窗口大小等) WebDriver driver = new ChromeDriver(); driver.manage().window().maximize(); driverMap.put(userIdentifier, driver); } return driverMap.get(userIdentifier); } // 关闭所有浏览器实例,用于场景结束后清理 public void closeAllDrivers() { driverMap.values().forEach(driver -> { if (driver != null) { driver.quit(); } }); driverMap.clear(); } }
2. 调整Step Definitions的注入方式
将原来直接注入WebDriver改为注入BrowserManager,在步骤中根据用户标识获取对应Driver:
import io.cucumber.java.After; import io.cucumber.java.en.Given; import io.cucumber.java.en.Then; import io.cucumber.java.en.When; import org.openqa.selenium.WebDriver; import org.openqa.selenium.support.ui.ExpectedConditions; import org.openqa.selenium.support.ui.WebDriverWait; import java.time.Duration; public class TableLockSteps { private final BrowserManager browserManager; private WebDriver user1Driver; private WebDriver user2Driver; // 通过PicoContainer注入BrowserManager(默认单例,确保同一场景内共享) public TableLockSteps(BrowserManager browserManager) { this.browserManager = browserManager; this.user1Driver = browserManager.getDriver("user1"); this.user2Driver = browserManager.getDriver("user2"); } @Given("User1用Access1账号在Chrome浏览器登录并打开某张表") public void user1_login_and_open_table() { user1Driver.get("你的登录页面URL"); // 执行Access1账号登录操作 // 打开目标表的操作 } @When("User2用Access2账号在另一Chrome浏览器登录,打开同一张表") public void user2_login_and_open_same_table() { user2Driver.get("你的登录页面URL"); // 执行Access2账号登录操作 // 打开目标表的操作 } @Then("应看到错误提示“the table is locked by user 1”") public void verify_lock_error_message() { WebDriverWait wait = new WebDriverWait(user2Driver, Duration.ofSeconds(10)); wait.until(ExpectedConditions.visibilityOfElementLocated(/* 错误提示元素定位器 */)); // 验证错误文本匹配 } @When("User1登出后,User2再次打开该表") public void user1_logout_and_user2_reopen_table() { // User1执行登出操作 user1Driver.get("登出页面URL"); // User2刷新或重新打开目标表页面 user2Driver.navigate().refresh(); } @Then("User2可编辑该表,最后User2登出") public void verify_table_editable_and_user2_logout() { // 验证表可编辑(如检查编辑按钮状态) // User2执行登出操作 user2Driver.get("登出页面URL"); } // 场景结束后清理所有浏览器进程 @After public void tearDown() { browserManager.closeAllDrivers(); } }
3. 关键注意事项
- PicoContainer会自动维护
BrowserManager的单例生命周期,确保同一场景内所有步骤共享同一个实例,从而管理两个独立的Driver。 - 如果框架有自定义Driver配置(如ChromeOptions、代理),可在
BrowserManager.getDriver()方法中统一添加,保证实例配置一致。 - 必须在
@After钩子中关闭所有Driver,避免浏览器进程残留。
内容的提问来源于stack exchange,提问作者Xoro
相关产品推荐
相关产品推荐

