Selenium:如何使 Web 驱动程序在执行另一个测试之前等待页面刷新

Posted

技术标签:

【中文标题】Selenium:如何使 Web 驱动程序在执行另一个测试之前等待页面刷新【英文标题】:Selenium: How to make the web driver to wait for page to refresh before executing another test 【发布时间】:2012-10-26 00:05:55 【问题描述】:

我正在 TestNG 中使用 Selenium Web 驱动程序编写测试用例,并且我有一个场景是我正在按顺序运行多个测试(请参阅下文)

@Test(priority =1)
public void Test1()

@Test(priority =2)
public void Test2() 

两个测试都是 AJAX 调用,其中会打开一个对话框,执行测试,然后关闭对话框,然后在页面顶部显示一条通知消息,每次成功测试后页面都会刷新

问题是: Test2 不等待页面刷新/重新加载。假设当 Test1 成功完成时, Test2 将在页面刷新之前启动(即它打开对话框,执行场景等)同时页面刷新(这必然发生在成功执行 Test1 之后)。现在由于页面刷新,由于Test2打开的对话框不再存在,然后Test2失败。

(另外,我不知道刷新页面需要多长时间。因此,我不想在执行Test2之前使用Thread.sleep(xxxx)

我也不觉得

driver.navigate().refresh()

将通过将它放在 Test2 之前解决我的问题,因为在这种情况下,我的页面将被刷新两次。问题是通过代码发生的刷新(不确定,因为它可能需要 1 秒或 3 秒或 5 秒)

【问题讨论】:

我有一个类似的场景 - 在确认对话框要求继续之前加载不确定 - 没有页面刷新。网页已加载 - 它正在处理 ajax。想要确认对话框是否出现。 关于测试范围的一般问题:成功重新加载不是测试的一部分吗?我会假设是这样,所以我会在测试 #1 结束时检查页面是否重新加载,然后测试 #2 甚至一开始就没有这个问题,因为问题是在测试 #1 结束时处理的(或者在 @AfterMethod 如果你不关心结果/不认为它真的是测试的一部分) 【参考方案1】:

如果您正在等待元素出现,那么

在 selenium rc 中,我们曾经使用 selenium.WaitForCondition("selenium.isElementPresent(\"fContent\")", "desiredTimeoutInMilisec") 来做到这一点

在 web 驱动中你可以使用这个实现同样的事情

WebDriverWait myWait = new WebDriverWait(webDriver, 45);
ExpectedCondition<Boolean> conditionToCheck = new ExpectedCondition<Boolean>()

    @Override
    public Boolean apply(WebDriver input) 
        return (input.findElements(By.id("fContent")).size() > 0);
    
;
myWait.until(conditionToCheck);

这样你可以在执行你的 test2 之前等待你的元素出现。

更新:

如果您正在等待页面加载,则可以在 Web 驱动程序中使用此代码:

public void waitForPageLoaded(WebDriver driver)

    ExpectedCondition<Boolean> expectation = new
ExpectedCondition<Boolean>() 
    
        public Boolean apply(WebDriver driver)
        
            return ((javascriptExecutor)driver).executeScript("return document.readyState").equals("complete");
        
    ;
    Wait<WebDriver> wait = new WebDriverWait(driver,30);
    try
    
        wait.until(expectation);
    
    catch(Throwable error)
    
        assertFalse("Timeout waiting for Page Load Request to complete.",true);
    

【讨论】:

我不想等待元素出现。我想等待页面重新加载/刷新,然后我只想执行 Test2 根据问题,我想在执行您的 test1 后页面会刷新,因此您无法获得执行测试用例 2 的所需元素。 问题是,如果您正在等待页面刷新,那么您不能等待元素 - 因为它们已经在页面上 但是当 WebDriver 继续运行时,元素通常不在最终位置。因此它们已加载但无法点击。 waitForPageLoaded(WebDriver webdriver) 函数在我的情况下完美运行!非常感谢【参考方案2】:

Here 是 C#.Net 中 WaitForPageLoad 实现的更好且经过测试的版本

public void WaitForPageLoad(int maxWaitTimeInSeconds) 
    string state = string.Empty;
    try 
        WebDriverWait wait = new WebDriverWait(_driver, TimeSpan.FromSeconds(maxWaitTimeInSeconds));

        //Checks every 500 ms whether predicate returns true if returns exit otherwise keep trying till it returns ture
        wait.Until(d = > 

            try 
                state = ((IJavaScriptExecutor) _driver).ExecuteScript(@"return document.readyState").ToString();
             catch (InvalidOperationException) 
                //Ignore
             catch (NoSuchWindowException) 
                //when popup is closed, switch to last windows
                _driver.SwitchTo().Window(_driver.WindowHandles.Last());
            
            //In IE7 there are chances we may get state as loaded instead of complete
            return (state.Equals("complete", StringComparison.InvariantCultureIgnoreCase) || state.Equals("loaded", StringComparison.InvariantCultureIgnoreCase));

        );
     catch (TimeoutException) 
        //sometimes Page remains in Interactive mode and never becomes Complete, then we can still try to access the controls
        if (!state.Equals("interactive", StringComparison.InvariantCultureIgnoreCase))
            throw;
     catch (NullReferenceException) 
        //sometimes Page remains in Interactive mode and never becomes Complete, then we can still try to access the controls
        if (!state.Equals("interactive", StringComparison.InvariantCultureIgnoreCase))
            throw;
     catch (WebDriverException) 
        if (_driver.WindowHandles.Count == 1) 
            _driver.SwitchTo().Window(_driver.WindowHandles[0]);
        
        state = ((IJavaScriptExecutor) _driver).ExecuteScript(@"return document.readyState").ToString();
        if (!(state.Equals("complete", StringComparison.InvariantCultureIgnoreCase) || state.Equals("loaded", StringComparison.InvariantCultureIgnoreCase)))
            throw;
    

【讨论】:

这在 ruby​​ 中会是什么样子? 太棒了! IWebElemt::click() 是否导致 html 或 Javascript 无关紧要。这个解决方案就像一个魅力。【参考方案3】:

如果您可以触发 URL 更改,这将起作用:

WebDriverWait wait = new WebDriverWait(yourDriver, TimeSpan.FromSeconds(5));
wait.Until(ExpectedConditions.UrlContains("/url-fragment"));

【讨论】:

以上是关于Selenium:如何使 Web 驱动程序在执行另一个测试之前等待页面刷新的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Java 中执行 Selenium 测试

python+selenium 如何变例输入使之每次执行脚本时都自增1

Selenium Web 驱动程序 Firefox 打开空白页

带有Python的Selenium Webdriver - 无法使用Selenium Web驱动程序在Web应用程序中提供输入(Date)

如何使用Selenium-Grid

如何使用Selenium-Grid