我正在尝试使用 Selenium 2 在 Liferay 门户服务器上自动化一些测试用例。许多 Liferay 操作会打开新的浏览器窗口弹出(如用户模拟)。这是一个示例链接(注意target="_blank"
):
<a title="(Opens New Window)" target="_blank" id="_125_xafr"
href="/web/guest?doAsUserId=xBRUWI85MvM%3D" class="taglib-icon aui-focus"
tabindex="0" role="menuitem">
<img alt="" src="/html/themes/control_panel/images/common/impersonate_user.png" class="icon">
Impersonate User
<span class="opens-new-window-accessible">(Opens New Window)</span>
</a>
切换到弹出窗口上下文相当简单:
String currentWindowHandle = driver.getWindowHandle();
if ( log.isDebugEnabled() ) log.debug( "currentWindowHandle='" + currentWindowHandle + "'" );
for ( String windowHandle : driver.getWindowHandles() ) {
if ( ! windowHandle.equals( currentWindowHandle ) ) {
boolean impersonationSuccess = false;
if ( log.isDebugEnabled() ) log.debug( "checking '" + windowHandle + "' impersonation alert notice" );
driver.switchTo().window( windowHandle );
try {
// wait for body to ensure page has loaded before checking to see if its impersonation page.
WebElement body = waitForElement( driver, By.xpath( "//body" ) );
WebElement noticeMessage = body.findElement(
By.xpath( "div[@class='popup-alert-notice' and a='Be yourself again.']/span[@class='notice-message']" ) );
if ( noticeMessage.getText().indexOf( "You are impersonating " + user.firstName + " " + user.lastName ) >= 0 ) {
impersonationSuccess = true;
break;
}
}
catch ( NoSuchElementException e ) {
if ( log.isDebugEnabled() ) {
log.debug( "did not find impersonation window '" + windowHandle + "'" );
}
}
finally {
if ( ! impersonationSuccess ) {
driver.switchTo().window( currentWindowHandle );
}
}
}
}
return currentWindowHandle;
但是,当我完成模拟后,我需要关闭弹出窗口。根据 WebDriver.close() 的 api,它将:
关闭当前窗口,如果它是当前打开的最后一个窗口,则退出浏览器。
如果我没看错,那么它应该只关闭弹出窗口,而不是 Firefox 实例(只要我打开另一个窗口,我会这样做,因为这只是一个弹出窗口)。但是,当我从弹出窗口的上下文中调用 close 时,它总是失败并显示:
org.openqa.selenium.WebDriverException:
org.apache.http.conn.HttpHostConnectException:
Connection to http://localhost:7055 refused
我发现一些关于这是 FirefoxDriver 中的错误的参考。有没有人有建议或解决方法?我想我可以在整个测试用例完成之前让弹出窗口保持打开状态,但是由于在我的测试套件中导致弹出窗口的操作数量众多,这可能很快变得不可行。
- - - - - - - 编辑 - - - - - - -
一个极其简化的测试用例:
@Test
public void testPopupClose() {
WebDriver driver = new FirefoxDriver();
driver.get( "http://lucastheisen.com/test/lucas_test_page.html" );
driver.findElement( By.id( "popup_link" ) ).click();
String mainWindowHandle = driver.getWindowHandle();
System.out.println( "currentWindowHandle='" + mainWindowHandle + "'" );
boolean foundPopup = false;
for ( String windowHandle : driver.getWindowHandles() ) {
if ( !windowHandle.equals( mainWindowHandle ) ) {
System.out.println( "checking '" + windowHandle + "' for taunt" );
driver.switchTo().window( windowHandle );
try {
driver.findElement( By.id( "taunt" ) );
foundPopup = true;
break;
}
catch ( NoSuchElementException e ) {
System.out.println( "'" + windowHandle + "' is not taunt window" );
}
finally {
if ( !foundPopup ) {
driver.switchTo().window( mainWindowHandle );
}
}
}
}
if ( foundPopup ) {
System.out.println( "found my popup, now try to close it..." );
driver.close();
}
System.out.println( "now try to continue working in original window" );
driver.switchTo().window( mainWindowHandle );
driver.findElement( By.id( "popup_link" ) );
driver.close();
assertTrue( true );
}
似乎表明这不是 FirefoxDriver 的真正问题。这表明只是创建一个弹出窗口,切换到它,然后关闭它,然后在主窗口中恢复工作不会导致 firefox 崩溃。这意味着原因要复杂得多,我想不出一种方法来创建一个简单的测试用例。我的真实代码基本上是一个使用 Liferay 的框架。它旨在成为我所有测试用例的基类,提供 impersonateUser(LiferayUser user) 等实用方法。我将在这里发布我的代码,但高度怀疑是否有人愿意花精力研究这个。现在我有一个解决方法,我可以关闭原始窗口,然后继续在弹出窗口中工作。如果我想出一个简化的测试用例来证明这个问题,我会再次编辑这篇文章。
------------- 编辑 2 --------------
我现在认为这与调试器有关。我正在使用 eclipse,如果我正在调试,并且正在逐步执行 close() 和 switchTo() 之间的代码,它会始终失败。您应该能够通过在我上面的简化示例测试用例中的这一行插入一个断点来重现:
System.out.println( "now try to continue working in original window" );
当代码在该断点处停止时,您会收到错误消息……不知道该怎么做,可能会提交错误。有什么建议么?
------------- 编辑 3 --------------
出于跟踪目的,这是我在此问题上打开的错误: