WebDriver Exploration Part-3(WebDriver Waits)

You may come across scenario's where you see elements on pages are loaded after some delay or after some specific event.
In such a case, our scripts can fail and complain it cannot find the element.

To tackle such scenario's we can have our script developed in such a way that it will wait for some predefined time before interacting with such type of elements

We will stick to our earlier example of clicking Gmail link on google home page, here we assume Gmail link appears after some delay on the home page, below are the ways we can tackle this

Sleeping till things appear on the page 😴

Yes. Sleeping till things get to normal.
Assuming that Gmail link appears within 10 seconds after the page is loaded, we can sleep for 10 seconds before interacting with it, check below

[TestMethod]
        public void Verify_Wait_Sleep()
        {
            InternetExplorerOptions options = new InternetExplorerOptions();
            options.IntroduceInstabilityByIgnoringProtectedModeSettings = true;
            options.RequireWindowFocus = true;
 
            IWebDriver driver = new InternetExplorerDriver(options);
            driver.Url = "https://www.google.com/";
 
            //Sleep till things get back to noraml :)
            System.Threading.Thread.Sleep(10000);
 
            //Locate Element By partial link text
            IWebElement gmailLink = driver.FindElement(
                By.PartialLinkText("mail"));
 
            //Click gmail link
            gmailLink.Click();
 
 
            //Driver close first instance
            driver.Quit();
 
        }

Now some BAD news

  1. This is the worst way to tackle waits in your scripts as we end up waiting for 10 seconds every time in our script where there is step to click on Gmail link
  2. If Gmail link appears after 2 seconds then also our script will wait for 10 seconds, so this is not smart enough

Implicit Waits

We can use an implicit wait of 10 seconds that is applicable to the life of WebDriver object instance.
So if the Gmail link appears before 10 seconds then the script will continue executing so we do not end up waiting for 10 seconds

Point to note implicit wait is global and in our case, it will wait for 10 seconds every time for finding elements before throwing no element found exception


[TestClass]
   public class WebdriverCourse
   {
       IWebDriver driver;
 
       [TestInitialize]
       public void Setup()
       {
 
           InternetExplorerOptions options = new InternetExplorerOptions();
           options.IntroduceInstabilityByIgnoringProtectedModeSettings = true;
           options.RequireWindowFocus = true;
           driver = new InternetExplorerDriver(options);
 
           //Implicit Wait
           driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
       }
 
       [TestMethod]
       public void Verify_Wait_ImplicitWait()
       {
 
           driver.Url = "https://www.google.com/";
 
         
           //Locate Element By partial link text
           IWebElement gmailLink = driver.FindElement(
               By.PartialLinkText("mail"));
 
           //Click gmail link
           gmailLink.Click();
 
 
           //Driver close first instance
           driver.Quit();
 
       }
}



In the above example, we have set up our driver object in the Setup method.
We have also set up implicit wait to 10 seconds 

Now as discussed earlier implicit wait once set up will stay for the lifetime of WebDriver instance.
So for each test method, we will have an implicit wait of 10 seconds, which we may not want.

What if we want to wait only for certain conditions?
Is there a setting which is not global, so we can apply it wherever it is required?

Yes. you can use explicit waits 

Explicit Waits

Explicit waits are smart waits which we can use to wait for certain condition to occur before proceeding with code execution

What can be those conditions?
Say you want to click the element only when it is visible, in our case the Gmail link 

Do I need to write code to figure out what is visible/invisible?
No. ExpectedConditions class utility class is already there which can help us with that 

We will use WebDriverWait and ExpectedConditions class to solve our wait concerns 

Note- To use ExpectedConditions class, install 'DotNetSeleniumExtras' package using nuget

[TestClass]
    public class WebdriverCourse
    {
        IWebDriver driver;
   
        [TestInitialize]
        public void Setup()
        {
 
            InternetExplorerOptions options = new InternetExplorerOptions();
            options.IntroduceInstabilityByIgnoringProtectedModeSettings = true;
            options.RequireWindowFocus = true;
            driver = new InternetExplorerDriver(options);
 
        }
 
        [TestMethod]
        public void Verify_Wait_ExplicitWait()
        {
 
            driver.Url = "https://www.google.com/";
 
 
            //Explicit Wait
            WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
            wait.Until(ExpectedConditions.ElementIsVisible(By.PartialLinkText("mail")));
 
            //Locate Element By partial link text
            IWebElement gmailLink = driver.FindElement(
                By.PartialLinkText("mail"));
 
            //Click gmail link
            gmailLink.Click();
 
 
            //Driver close first instance
            driver.Quit();
 
        }
}


Conclusion
  1. Do not use Sleep method for waits
  2. Do not use implicit and explicit waits both as it can lead to unpredictable wait times
  3. Use explicit wait only in your code
  4. Decide the maximum wait time out wisely as it can increase your overall execution time of the test suite.








Comments

Popular posts from this blog

Specflow -Part3(Working with tables using Specflow.Assist.Dynamic)

Specflow -Part4(Specflow Scenario Outline and Feature Background )

C# Basics-Part 2(Namespaces,Properties,Constants and Read-Only Fields)