Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clarification of the cause of mixing Implicit and Explicit waits in Selenium doc

I was reading the SeleniumHQ documentation and came across the following statements.

"WARNING: Do not mix implicit and explicit waits. Doing so can cause unpredictable wait times. For example setting an implicit wait of 10s and an explicit wait of 15 seconds, could cause a timeout to occur after 20 seconds."

For some reason, I cannot get this to make sense. The total timeout 20s is the main confusion point for me. Can anyone explain if I am missing something?

EDIT

My question is not about the implementation/consequences of mixing those waits. It's entirely about the statements and calculation of timeout on the doc.

2nd Edit

Looks like the doc is correct according to the tests below. I still need the explanation though.

Just Implicit wait

using System;
using System.Diagnostics;
using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;

namespace Test
{
    [TestFixture]
    public class Test
    {
        private IWebDriver _webDriver;

        [Test]
        public void ExplicitVsImplicitWaitTest()
        {
            _webDriver = new ChromeDriver();
            _webDriver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(10));
            _webDriver.Navigate().GoToUrl("https://www.google.com/");
            _webDriver.Manage().Window.Maximize();

            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();

            try
            {
                //new WebDriverWait(_webDriver, TimeSpan.FromSeconds(15)).Until(
                //ExpectedConditions.ElementExists(By.CssSelector("Should Fail")));
                _webDriver.FindElement(By.CssSelector("Should Fail"));
            }
            catch ( NoSuchElementException exception)
            //catch ( OpenQA.Selenium.WebDriverTimeoutException)
            {
                stopwatch.Stop();
                Console.WriteLine(stopwatch.Elapsed);
            }

            _webDriver.Quit();

        }
    }
}

Time in second: 00:00:10.0167290

Just Explicit wait

using System;
using System.Diagnostics;
using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Support.UI;

namespace Test
{
    [TestFixture]
    public class Test
    {
        private IWebDriver _webDriver;

        [Test]
        public void ExplicitVsImplicitWaitTest()
        {
            _webDriver = new ChromeDriver();
            //_webDriver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(10));
            _webDriver.Navigate().GoToUrl("https://www.google.com/");
            _webDriver.Manage().Window.Maximize();

            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();

            try
            {
                new WebDriverWait(_webDriver, TimeSpan.FromSeconds(15)).Until(
                ExpectedConditions.ElementExists(By.CssSelector("Should Fail")));
                _webDriver.FindElement(By.CssSelector("Should Fail"));
            }
            //catch ( NoSuchElementException exception)
            catch ( OpenQA.Selenium.WebDriverTimeoutException)
            {
                stopwatch.Stop();
                Console.WriteLine(stopwatch.Elapsed);
            }

            _webDriver.Quit();

        }
    }
}

Time in second: 00:00:15.2463079

Mixed, Explicit and Implicit both

using System;
using System.Diagnostics;
using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Support.UI;

namespace Test
{
    [TestFixture]
    public class Test
    {
        private IWebDriver _webDriver;

        [Test]
        public void ExplicitVsImplicitWaitTest()
        {
            _webDriver = new ChromeDriver();
            _webDriver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(10));
            _webDriver.Navigate().GoToUrl("https://www.google.com/");
            _webDriver.Manage().Window.Maximize();

            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();

            try
            {
                new WebDriverWait(_webDriver, TimeSpan.FromSeconds(15)).Until(
                ExpectedConditions.ElementExists(By.CssSelector("Should Fail")));
                _webDriver.FindElement(By.CssSelector("Should Fail"));
            }
            //catch ( NoSuchElementException exception)
            catch ( OpenQA.Selenium.WebDriverTimeoutException)
            {
                stopwatch.Stop();
                Console.WriteLine(stopwatch.Elapsed);
            }

            _webDriver.Quit();

        }
    }
}

Time in second: 00:00:20.5771817

like image 671
Saifur Avatar asked Apr 06 '15 15:04

Saifur


People also ask

Why implicit wait is not recommended?

Hey Aaron, the main disadvantage of implicit wait is that it slows down test performance. The implicit wait will tell to the web driver to wait for certain amount of time before it throws a "No Such Element Exception".

What is the difference between the implicit wait & WebDriver wait?

Once this time is set, WebDriver will wait for the element before the exception occurs. Once the command is in place, Implicit Wait stays in place for the entire duration for which the browser is open.

What is difference between thread sleep and implicit wait in Selenium?

One of which is Implicit wait which allows you to halt the WebDriver for a particular period of time until the WebDriver locates a desired element on the web page. The key point to note here is, unlike Thread. sleep(), it does not wait for the complete duration of time.

Does implicit wait applied to all elements?

Note: Implicitly wait is applied globally which means it is always available for all the web elements throughout the driver instance. It implies if the driver is interacting with 100 elements then, Implicitly wait is applicable for all the 100 elements.


1 Answers

My question is not about the implementation of those waits. It's entirely about the statements and calculation of timeout on the doc.

But you have to know how they are implemented to make sense of what is going on. Here is what happens with your mix of the two types of waits. I'm kipping over those steps that are not important for the discussion.

  1. Your script sets an implicit wait.

  2. Your script starts an explicit wait checking whether the element exists. The explicit wait works by polling. So it sends a command to the browser to check for the existence of the element.

  3. Because of the implicit wait already set, the command sent to the browser takes 10 seconds to return a failure.

  4. Your explicit wait checks whether it has reached its time limit which is 15s. It is currently at 10s (+ a tiny amount of time taken to execute the script, network latency, etc.) into the wait, which is less then 15s. So it is not done waiting and reissues the same command as in step 2 above.

  5. Because of the implicit wait, the command sent to the browser takes 10 seconds to return a failure.

  6. When the explicit wait checks again for its own timeout, more than 15s have elapsed, so it times out.

So the explicit wait polls twice, and each time takes 10 seconds which mean 20 seconds total (plus a tiny amount of time to account for the bookkeeping).

An explicit wait does not do anything to detect and compensate for an implicit wait that has been set. And it does not continue running in parallel to the commands it sends to the browser. While a browser command executes, the explicit wait is not doing any bookkeeping or able to time out. It has to wait for the browser command to complete before checking whether it should time out.

like image 141
Louis Avatar answered Oct 20 '22 06:10

Louis