Selenium stops to work after call FindElements

后端 未结 2 1390
花落未央
花落未央 2021-01-28 02:26

Sometimes when I call the Selenium FindElements(By), it throws an exception and my driver stops to work. The parameter \"BY\" maybe can be the problem: when I use a different by

相关标签:
2条回答
  • 2021-01-28 02:36

    This is a known issue for selenium, the webdriver server has a maximum timeout limit of 60 seconds for each request and there isn't a way that i'm aware of to change that, i suggest that you consider using explicit wait before using FindElement(), although this issue might occur, there's a workaround for this issue that has worked for me, using extension methods that i have implemented, the idea is to wait for specific condition so that if the webdriver threw an exception that says it has waited for the maximum limit of 60 secs, you could handle that by trying to wait for a specific condition repeatedly for a specific period of time, each time you loop a new request is sent to the webdriver server.

        public static void WaitUntil(this IWebDriver webDriver, Func<IWebDriver, bool> predicate, TimeSpan timeout)
        {
            var dtStart = DateTime.Now;
    
            while (true)
            {
                try
                {
                    if (!predicate(webDriver))
                        throw new Exception();
    
                    break;
                }
                catch (Exception ex)
                {
                    if (DateTime.Now.Subtract(dtStart) >= timeout)
                        throw ex;
                }
    
                Thread.Sleep(30000);
            }
        }
        public static void WaitUntil(this IWebDriver webDriver, Func<IWebDriver, IWebElement> predicate, TimeSpan timeout)
        {
            var dtStart = DateTime.Now;
    
            while (true)
            {
                try
                {
                    predicate(webDriver);
                    break;
                }
                catch (Exception ex)
                {
                    if (DateTime.Now.Subtract(dtStart) >= timeout)
                        throw ex;
                }
    
                Thread.Sleep(30000);
            }
        }
    

    you could for example use the extension methods like that

    webDriver.WaitUntil(w => w.Title == "title", TimeSpan.FromMinutes(2));
    

    or

    webDriver.WaitUntil(ExpectedConditions.TitleIs("title"), TimeSpan.FromMinutes(2));
    

    or

    webDriver.WaitUntil(ExpectedConditions.ElementIsVisible(By.Id("elementId")), TimeSpan.FromMinutes(2));
    

    Update

    After reviewing your last comment, you said that you got some elements when you have used FindElements(By.TagName("input"); that mean that the selector you are using is causing the problem, you could find elements by tag name then filter the results by the attribute value, or if you are certain that the selector you are using is correct and is not behaving correctly, try to debug the issue, also if there's any javascript that is responsible for setting the attribute value, make sure that it runs first using implicit or explicit wait before calling FindElement().

    0 讨论(0)
  • 2021-01-28 03:00

    I found the problem. I'm using a method in all my test suit to wait the loading message dismiss. But it try using jquery and not all pages in my application use it.

    So, selenium give up try execute jquery after 60 seconds and returns a timeout error, but this error does not broken the Selenium driver, only the FindElements then it returns a empty list. And when it try to return the empty list, all the drive broke.

    The original method:

    public void WaitLoadingMessage(int timeout)
    {
        while (timeout > 0)
        {
            try
            {
                var loadingIsVisible = _js.ExecuteScript("return $('#loading-geral').is(':visible');").ToString();
    
                if (loadingIsVisible.ToLower() == "false")
                    break;
    
                Thread.Sleep(1000);
                timeout -= 1000;
            }
            catch (Exception ex)
            {
                if (!ex.Message.ToLower().Contains("$ is not defined"))
                    throw;
            }
        }
    }
    

    And the correction:

    public void WaitLoadingMessage(int timeout)
    {
        while (timeout > 0)
        {
            try
            {
                var loadingIsVisible = _js.ExecuteScript("return $('#loading-geral').is(':visible');").ToString();
    
                if (loadingIsVisible.ToLower() == "false")
                    break;
    
                Thread.Sleep(1000);
                timeout -= 1000;
            }
            catch (Exception ex)
            {
                if (!ex.Message.ToLower().Contains("$ is not defined"))
                    throw;
    
                break;
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题