1. 概述
本文将介绍如何使用Selenium处理浏览器标签页。实际测试中,点击链接或按钮时经常会在新标签页打开页面。这种场景下,我们需要正确处理标签页才能继续执行测试。本文涵盖在新标签页打开页面、切换标签页和关闭标签页的操作。所有示例将基于测试站点 https://testpages.herokuapp.com。
2. 环境准备
基于 WebDriver 设置,我们创建一个 SeleniumTestBase 基类,负责 WebDriver 的初始化和清理。测试类将继承该基类。同时定义一个标签页处理的辅助类 TabHelper,包含打开、切换和关闭标签页的方法。这些方法将在后续章节详细说明。我们在 SeleniumTestBase 中初始化 TabHelper 实例。所有示例使用 JUnit5。
初始化代码放在带 @BeforeAll 注解的 init() 方法中:
@BeforeAll
public static void init() {
setupChromeDriver();
}
清理方法在所有测试结束后关闭整个浏览器:
@AfterAll
public static void cleanup() {
if (driver != null) {
driver.quit();
}
}
3. 基础知识
3.1. 链接的 target 属性
当点击链接或按钮在新标签页打开页面时,就需要处理标签页。网站中设置了 target="_blank"
属性的链接会在新标签页打开,例如:
<a href="https://www.baeldung.com/" target="_blank">Baeldung.com</a>
这类链接会将目标页面(如 https://www.baeldung.com)在新标签页打开。
3.2. 窗口句柄
在Selenium中,每个标签页都有一个唯一的窗口句柄(字符串)。Chrome标签页的句柄以 CDwindow
开头,后跟32个十六进制字符,例如 CDwindow-CDE9BEF919431FDAA0FC9CB7EBBD4E1A
。切换到特定标签页时必须使用窗口句柄,因此测试中需要存储这些句柄。
4. 标签页操作
4.1. 打开标签页
Selenium 4.0+ 版本无需使用JavaScript或浏览器快捷键即可打开新标签页。WebDriver 提供以下方法:
driver.switchTo().newWindow(WindowType.TAB);
如前所述,某些链接设置了 target
属性。这种情况下无需手动打开标签页,但需要处理切换和关闭操作。虽然这类链接会在新标签页打开页面,但不会自动切换到新标签页,需要手动处理。一个简单粗暴的方案是:比较点击链接前后的窗口句柄集合,新增的句柄就是新标签页。
通过 WebDriver 的以下方法获取窗口句柄集合和当前标签页句柄:
driver.getWindowHandles();
driver.getWindowHandle()
利用这些方法,我们在 TabHelper 类中实现辅助方法:打开链接并切换到新标签页(仅当确实打开新标签页时才切换):
String openLinkAndSwitchToNewTab(By link) {
String windowHandle = driver.getWindowHandle();
Set<String> windowHandlesBefore = driver.getWindowHandles();
driver.findElement(link).click();
Set<String> windowHandlesAfter = driver.getWindowHandles();
windowHandlesAfter.removeAll(windowHandlesBefore);
Optional<String> newWindowHandle = windowHandlesAfter.stream().findFirst();
newWindowHandle.ifPresent(s -> driver.switchTo().window(s));
return windowHandle;
}
核心逻辑:通过点击前后的句柄集合差集找到新标签页句柄。方法还返回切换前的原始句柄,方便后续操作。
4.2. 切换标签页
存在多个标签页时,需要手动切换。使用以下语句切换到指定句柄的标签页(destinationWindowHandle
为目标句柄):
driver.switchTo().window(destinationWindowHandle)
实现辅助方法,接收目标句柄并切换,同时返回切换前的当前句柄:
public String switchToTab(String destinationWindowHandle) {
String currentWindowHandle = driver.getWindowHandle();
driver.switchTo().window(destinationWindowHandle);
return currentWindowHandle;
}
4.3. 关闭标签页
测试结束后或不再需要某些标签页时,应将其关闭。Selenium 提供关闭当前标签页的方法(如果是最后一个标签页则关闭整个浏览器):
driver.close();
利用该方法可实现关闭除指定标签页外的所有标签页:
void closeAllTabsExcept(String windowHandle) {
for (String handle : driver.getWindowHandles()) {
if (!handle.equals(windowHandle)) {
driver.switchTo().window(handle);
driver.close();
}
}
driver.switchTo().window(windowHandle);
}
逻辑:遍历所有句柄,关闭非目标标签页,最后确保切换回保留的标签页。
进一步封装关闭除当前标签页外的所有标签页:
void closeAllTabsExceptCurrent() {
String currentWindow = driver.getWindowHandle();
closeAllTabsExcept(currentWindow);
}
在 SeleniumTestBase 的 @AfterEach 方法中调用此方法,确保每个测试后清理多余标签页,避免测试间相互影响:
@AfterEach
public void closeTabs() {
tabHelper.closeAllTabsExceptCurrent();
}
4.4. 使用快捷键处理标签页
⚠️ 踩坑提示:过去可通过浏览器快捷键(如 Ctrl+T)处理标签页,但由于 ChromeDriver 的更新,此方法已失效。
5. 测试用例
通过简单测试验证 TabHelper 的功能。测试类需继承 SeleniumTestBase:
class SeleniumTabsLiveTest extends SeleniumTestBase {
//...
}
在测试类中定义常量(URL 和定位器):
By LINK_TO_ATTRIBUTES_PAGE_XPATH = By.xpath("//a[.='Attributes in new page']");
By LINK_TO_ALERT_PAGE_XPATH = By.xpath("//a[.='Alerts In A New Window From JavaScript']");
String MAIN_PAGE_URL = "https://testpages.herokuapp.com/styled/windows-test.html";
String ATTRIBUTES_PAGE_URL = "https://testpages.herokuapp.com/styled/attributes-test.html";
String ALERT_PAGE_URL = "https://testpages.herokuapp.com/styled/alerts/alert-test.html";
测试场景1:打开新标签页并切换 验证打开新标签页后能正确切换,并保持两个标签页:
void givenOneTab_whenOpenTab_thenTwoTabsOpen() {
driver.get(MAIN_PAGE_URL);
String mainWindow = tabHelper.openLinkAndSwitchToNewTab(LINK_TO_ATTRIBUTES_PAGE_XPATH);
assertEquals(ATTRIBUTES_PAGE_URL, driver.getCurrentUrl());
tabHelper.switchToTab(mainWindow);
assertEquals(MAIN_PAGE_URL, driver.getCurrentUrl());
assertEquals(2, driver.getWindowHandles().size());
}
测试场景2:关闭多余标签页 验证关闭除主标签页外的所有标签页:
void givenTwoTabs_whenCloseAllExceptMainTab_thenOneTabOpen() {
driver.get(MAIN_PAGE_URL);
String mainWindow = tabHelper.openLinkAndSwitchToNewTab(LINK_TO_ATTRIBUTES_PAGE_XPATH);
assertEquals(ATTRIBUTES_PAGE_URL, driver.getCurrentUrl());
assertEquals(2, driver.getWindowHandles().size());
tabHelper.closeAllTabsExcept(mainWindow);
assertEquals(1, driver.getWindowHandles().size());
assertEquals(MAIN_PAGE_URL, driver.getCurrentUrl());
}
6. 总结
本文介绍了使用Selenium处理浏览器标签页的核心操作:
- ✅ 通过窗口句柄区分不同标签页
- ✅ 打开新标签页(包括自动处理
target="_blank"
链接) - ✅ 在标签页间切换
- ✅ 关闭指定或所有标签页
完整实现代码可在 GitHub 查看。