【问题标题】:How do i use the Wait mechanism in Selenium?如何使用 Selenium 中的等待机制?
【发布时间】:2014-03-15 08:40:15
【问题描述】:
  1. 我正在使用 JSF 为 J2EE 应用程序编写 Selenium 2 + C# 和 Nunit。
  2. 可能因为它是基于 Ajax 或网络延迟的,所以 Selenium 会失败,除非我保留一些“等待”机制。我列出了我正在尝试的 4 种方法。但是,仍然有一些情况下测试挂起,或者说它无法获取元素,或者元素已过时。这些错误是随机的,并不一致。
  3. 所以我不断减少等待以减轻陈旧性,或增加等待以启用元素处理。当然,有时我会等待很长时间。
  4. 我一直在混淆各种方法,因为它们对我来说是一种魔法。下面列出的方法有什么问题吗?

谢谢。

A) 等待进度条

public void WaitForProgressBar(ref Screenshot ss, WebDriverWait wait, ref IWebElement progressBar, ref IWebDriver _driver)
            {
            try
                {
                progressBar = wait.Until<IWebElement>((d) =>
                {
                    return d.FindElement(By.XPath("//span[@id='_viewRoot:status.start']/img[@src='images/pleasewait.gif']"));
                });
                }
            catch
                {
                _logger.Debug("Could not locate progress bar");
                }

            progressBar = _driver.FindElement(By.XPath("//span[@id='_viewRoot:status.start']/img[@src='images/pleasewait.gif']"));
            while (progressBar.Displayed)
                System.Threading.Thread.Sleep(100);

            _logger.Debug("Sleeping");

            while (progressBar.Displayed)
                System.Threading.Thread.Sleep(300);

            ss = ((ITakesScreenshot)_driver).GetScreenshot();
            ss.SaveAsFile("C:/WaitingForProgressBar.png", System.Drawing.Imaging.ImageFormat.Png);
            }

B) 休眠,然后调用 WaitForProgressBar()

System.Threading.Thread.Sleep(2500);
logInAndConfigureHospital.WaitForProgressBar(ref ss, wait, ref progressBar, ref _driver);

C) 调用 WaitForProgressBar() 然后休眠

logInAndConfigureHospital.WaitForProgressBar(ref ss, wait, ref progressBar, ref _driver);
System.Threading.Thread.Sleep(250);

D) 使用等待直到

IWebElement checkBoxSelectAll = wait.Until<IWebElement>((d) =>
        {
            return d.FindElement(By.XPath("//div[@id='convertHandlerForm:ConvertHandlerLines_header']/table/tbody/tr/td/input"));
        });
        checkBoxSelectAll.Click(); 

【问题讨论】:

    标签: selenium selenium-webdriver


    【解决方案1】:

    两种说法

    while (progressBar.Displayed)
    

    进度条一消失就会抛出StaleElementReferenceException,因为DOM已经改变。

    在尝试检查进度条可见性时,您需要一个处理不同异常的方法。下面的扩展方法就是这样做的,如果未找到元素或抛出异常,则返回 null 值。

    public static class WebDriverExtensions
    {
        /// <summary>
        /// Wait Get an element. 
        /// </summary>
        /// <param name="driver"></param>
        /// <param name="by"></param>
        /// <param name="timeout">timeout in seconds to wait for element</param>
        /// <returns>the element, else null</returns>
        public static IWebElement WaitGetElement(this IWebDriver driver, By by, 
                int timeout = 10, bool checkForVisibility=false)
        {
            IWebElement element;
            WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeout));
            wait.IgnoreExceptionTypes(typeof(StaleElementReferenceException));
            wait.Message = string.Format("Timed out after waiting {0} seconds for the {1} field ", timeout, by.ToString());
            try
            {
                if (checkForVisibility)
                {
                    element = wait.Until(ExpectedConditions.ElementIsVisible(by));
                }
                else
                {
                    element = wait.Until(ExpectedConditions.ElementExists(by));
                }
            }
            catch (NoSuchElementException) { element = null; }
            catch (WebDriverTimeoutException) { element = null; }
            catch (TimeoutException) { element = null; }
    
            return element;
        }
    }
    

    现在您可以使用上面的扩展方法,使用下面的方法等待进度条。这将等待至少 1 秒,让进度条消失。

    public bool WaitForProgressComplete(int waitTimeoutInSecs = 60)
    {
       bool isComplete = false;
       var sw = new Stopwatch();
       sw.Start();
       while (!isComplete && sw.Elapsed.TotalSeconds < waitTimeoutInSecs)
       {
          //try locate the progress bar, checking for max 1 sec(internally polls every 500ms) 
          //Check for visibility true (last param)
       progressBar = this.Driver.WaitGetElement(By.XPath("//span[@id='_viewRoot:status.start']/img[@src='images/pleasewait.gif']"), 1, true);
          isComplete = (progressBar == null);
       }
    
       sw.Stop();
       return isComplete;
    }
    

    这里唯一需要注意的是,如果进度条最初显示的时间少于 1 秒,则此方法将在进度条显示之前返回。在这种情况下,您可以在WaitGetElement 调用中增加等待超时,或者预先放置一个静态等待。

    【讨论】:

      猜你喜欢
      • 2023-03-10
      • 2013-12-31
      • 2021-12-18
      • 1970-01-01
      • 1970-01-01
      • 2011-09-06
      • 2012-05-11
      • 1970-01-01
      相关资源
      最近更新 更多