【问题标题】:Switch from child to parent window in Selenium Webdriver在 Selenium Webdriver 中从子窗口切换到父窗口
【发布时间】:2014-11-14 17:19:31
【问题描述】:

我正在使用 Eclipse 在 Selenium WebSriver 中创建测试脚本,并且在我有一个父窗口的场景中遇到了障碍,我单击该窗口上的链接并打开一个子窗口。然后我想关闭子窗口并在父窗口上再次执行功能。

我的代码如下:

public static void daysInStockSelectContract(InternetExplorerDriver driver) {
    driver.findElement(By.xpath(".//*[@id='page-content']/table/tbody/tr[1]/td[1]/a")).click();

    for(String winHandle : driver.getWindowHandles()) {
        driver.switchTo().window(winHandle);
        driver.close();
    }
 }

当我运行上面的代码时,子窗口保持打开而父窗口关闭,这与我想要的效果相反。控制台中还会显示如下错误:

“线程“主”org.openqa.selenium.remote.SessionNotFoundException 中的异常:会话 1ff55fb6-71c9-4466-9993-32d7d9cae760 不存在”

我正在为我的 Selenium 脚本使用 IE WebDriver。


更新 - 2014 年 11 月 17 日

Subh,这是我从您发送的链接中使用的代码,不幸的是它似乎不起作用。

public static void daysInStockSelectContract(InternetExplorerDriver driver) {
    //get the parent handle before clicking on the link
    String winHandleBefore = driver.getWindowHandle();

    driver.findElement(By.xpath(".//*[@id='page-content']/table/tbody/tr[1]/td[1]/a")).click();

    // the set will contain only the child window now. Switch to child window and close it.
    for(String winHandle : driver.getWindowHandles()) {
        driver.switchTo().window(winHandle);
    }
    driver.close();
    driver.switchTo().window(winHandleBefore);
}

【问题讨论】:

    标签: java eclipse selenium selenium-webdriver


    【解决方案1】:

    可能是切换到子窗口不正确。

    因此,'driver.close()' 正在关闭父窗口,而不是子窗口。此外,由于父窗口已关闭,这意味着会话已丢失,这会导致错误 'SessionNotFoundException'

    此链接将在properly switching between windows 中为您提供帮助

    另外,只是一个建议。与其将 "driver" 作为参数传递,不如将其设为静态变量。类中的所有方法及其子类都可以轻松访问它,并且您不必每次都将其传递给方法.. :)


    以下是您在评论中要求的代码(与上述问题无关)

    public class Testing_anew {
    
        public static WebDriver driver;
    
        public static void main(String args[]) throws InterruptedException{
    
            driver = new FirefoxDriver();
    
            driver.manage().window().maximize();
    
            driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
    
          }
    
        public static void testmethod(){
    
        driver.findElement(By.xpath("//some xpath")).click();
       }
    

    更新代码 19/11/14

    public static void daysInStockSelectContract(InternetExplorerDriver driver) {
        //get the parent handle before clicking on the link 
        String winHandleBefore = driver.getWindowHandle();
    
        System.out.println("Current handle is: "+winHandleBefore);
    
        driver.findElement(By.xpath(".//*[@id='page-content']/table/tbody/tr[1]/td[1]/a")).click();
    
        // Iterating through the set of window handles till the child window's handle, that is infact
        // not equal to the current window handle, is found
        for(String winHandle : driver.getWindowHandles()) {
           if(!winHandle.equals(winHandleBefore)){
                    System.out.println("Child handle is: "+ winHandle);
                    //Sleeping for 4 seconds for detecting Child window
                    try{
                        Thread.sleep(4000);
                       }catch(InterruptedException e){
                        System.out.println("Caught exception related to sleep:"+e.getMessage());
                       }
                    driver.switchTo().window(winHandle);
                    break;
                }
        } 
    
        System.out.println("AFTER SWITCHING, Handle is: "+driver.getWindowHandle());
    
        driver.close();
    
        //Sleeping for 4 seconds for detecting Parent window
        try{
            Thread.sleep(4000);
           }catch(InterruptedException e){
            System.out.println("Caught exception related to sleep:"+e.getMessage());
           }
    
        driver.switchTo().window(winHandleBefore); // Switching back to parent window
    
         System.out.println("NOW THE CURRENT Handle is: "+driver.getWindowHandle());
    
         //Now perform some user action here with respect to parent window to assert that the window has switched properly
    
    
    } 
    

    【讨论】:

    • 嗨,Subh,感谢您的更新。控制台中的错误输出现在显示两个不同的句柄,如下所示“当前句柄为:f5ec1357-830a-4ea6-9632-d1da8ac90bda 子句柄为:ffe5b144-a6bd-49b4-b034-b0c6e2190280 线程“主”组织中的异常.openqa.selenium.NoSuchWindowException:未找到窗口(警告:服务器未提供任何堆栈跟踪信息)命令持续时间或超时:1.59 秒”希望这会有所帮助:-)
    • 问题出在切换到 Window 时,即在此代码中 driver.switchTo().window(winHandle);。尝试使用 FirefoxDriver 运行相同的代码。如果它运行,请告诉我。
    • 嗨,Subh,我已经在 Firefox 中运行了代码,它确实有效。但是,我在 IE 上运行它,因为我正在测试的网站是一个内部网站,所有用户都在 IE 上。
    • 另外,它可能无关紧要,但在 Firefox 中,当操作完成时,控制台会显示以下“当前句柄为:{dee6212a-ff49-42f0-b413-00dfa4178b23} 子句柄为:{15715675 -3a64-45f5-9342-641c025ee171} 切换后,句柄为:{15715675-3a64-45f5-9342-641c025ee171} 线程“主”org.openqa.selenium.NoSuchWindowException 中的异常:未找到窗口。浏览器窗口可能已关闭。”所以即使动作已经完成,“AFTER SWITCHING”文本暗示我们和孩子在同一个句柄上:-/
    • 你用的是哪个版本的IE?
    【解决方案2】:

    当您遍历 windowHandles 时,第一个句柄是父句柄。所以当你说driver.close() 时,父窗口正在关闭。使用以下代码可以避免这种情况:

    public static void daysInStockSelectContract(InternetExplorerDriver driver) {
        //get the parent handle before clicking on the link
        String parentHandle = driver.getWindowHandle();
    
        driver.findElement(By.xpath(".//*[@id='page-content']/table/tbody/tr[1]/td[1]/a")).click();
    
        //get all the window handles and assign it to a set 
        //It will include child window and parentwindow
        Set<String> windowHandles = driver.getWindowHandles();
    
        System.out.println("No of Window Handles: " + windowHandles.size());
    
        //remove the parent handle from the set
        windowHandles.remove(parentHandle);
    
        // the set will contain only the child window now. Switch to child window and close it.
        for(String winHandle : driver.getWindowHandles()) {
    

    强文本 driver.switchTo().window(winHandle); 司机.close(); } }

    如果您得到的大小为 1(没有 windowHandles 为 1)或收到相同的错误消息,那么该窗口可能是一个警告框。要处理警报框,您可以在单击链接后使用以下代码。

    Alert alert = driver.switchTo().alert();
    alert.accept();
    

    试试这段代码进行调试

    public static void daysInStockSelectContract(InternetExplorerDriver driver) {
        // get the parent handle before clicking on the link
        String parentHandle = driver.getWindowHandle();
        System.out.println("ParentHandle : " + parentHandle);
        driver.findElement(
                By.xpath(".//*[@id='page-content']/table/tbody/tr[1]/td[1]/a"))
                .click();
    
        // get all the window handles and assign it to a set
        // It will include child window and parentwindow
        Set<String> windowHandles = driver.getWindowHandles();
    
        System.out.println("No of Window Handles: " + windowHandles.size());
    
        // remove the parent handle from the set
        windowHandles.remove(parentHandle);
    
        // the set will contain only the child window now. Switch to child
        // window and close it.
        for (String winHandle : driver.getWindowHandles()) {
            driver.switchTo().window(winHandle);
            System.out.println("Child Handle : " + winHandle);
            driver.close();
        }
    
        // get the window handles again, print the size
        windowHandles = driver.getWindowHandles();
        System.out.println("No of Window Handles: " + windowHandles.size());
        for (String winHandldes : windowHandles) {
            System.out.println("Active Window : " + winHandldes);
        }
    
        driver.switchTo().window(parentHandle);
    }
    

    【讨论】:

    • 嘿,非常感谢您对此的帮助 :-) 不幸的是,我仍然遇到一个问题,即子窗口启动,但父窗口仍然关闭。我得到的错误是:“线程“主”org.openqa.selenium.remote.SessionNotFoundException中的异常:会话84742c89-b161-4112-9de7-2fde02cdacb8不存在命令持续时间或超时:0毫秒”你有什么想法吗?可能是什么原因造成的?再次感谢。
    • 这段代码有效吗?如果是,请采纳答案:)
    • 您好,我仍然遇到这个问题。希望你能帮助解决我仍然遇到的问题:-)
    • 你能试试上面编辑的代码吗?我添加了一个额外的行来打印窗口句柄的数量。如果您仍然收到错误或大小为零,那么您的另一个窗口将充当警报窗口。我还添加了处理警报的代码。
    • 您好,感谢您的回复。我添加了处理警报框的代码,但我认为这不是问题,因为我收到一条错误消息:“线程“主”org.openqa.selenium.NoAlertPresentException 中的异常:没有警报处于活动状态”接下来我尝试是在代码行中添加打印窗口句柄的数量。我得到的值是'2'。任何想法这可能是什么?
    【解决方案3】:

    我设法通过使用上述 Subh 概述的步骤解决了这个问题。特别是,确保在“Internet 选项”的“安全”选项卡上禁用“启用保护模式”

    【讨论】: