Checking If An Element Is Present/Displayed With WebDriver

On several sites I have worked on in recent years there has always been a check scenario whereby I have wanted to check that something isn’t on the page, such as a error message or a field not required in a given context.

WebDriver by design, as its intended to show you what the user can see, will return a NoSuchElementException if given a locator for an element that shouldn’t be on the page.

So what most people write is a function containing a try catch and subsequently return a bool indicating if the element is on the page or not. Something like this:


In my opinion this is a nice way to do it, you could of course return the exception and assert against that, but I find bool a nicer approach. But what is often overlooked with this approach is the default timeout for the driver. If you haven’t altered this, then it will be 0 so you won't have this problem, but I know a lot of people do to reduce flakiness, so lets says its 20 seconds. What happens when you run the above code is WebDriver will try to find the element for that time duration, making it look like your test has hung, before it declares it not present. This can be a lengthy amount of time depending how many times you are looking for something not to be present during your suite.

One way to achieve this is to reduce the driver timeout before the try catch and then setting it back to the appropriate value afterwards. This could be done in a helper class or if you have created a custom driver can be added as a method on that. Something like this:


Another way to do this is with the IDisposable interface as introduce to me by a chap called James Barker, use the using command and then do your call inside there, then the timeout would be automatically set back after the call during the disposal. Something like this:


However if you are following the PageObject approach and using the PageFactory then you would want to be passing the appropriate IWebElement in to the method. You would initially think that this isn't possible because the element would be null, but it actually isn't because at the point of initialising the PageObject with the factory is creates it as an IWebElementProxy (something like this, some black magic :) ) so you can actually pass the IWebElement to a method and call the IsDisplayed() method inside a try catch like above.

I achieve this with the following code, but note that this code isn't full proof because if the element is present but not displayed you will get false, if the element isn't present you will get false. So if you intention is to check that the element isn't in the code at all, your probably better following a pattern above. Issue there will be you will likely have to duplicate your locator or you could do some nasty reflection to get the locator, or stick it in a const string. However I haven't had a need to do that and for me as long as a user cannot see the element, I am happy.


So there you have it, several approaches to dealing with checking if an element is present/displayed.
Hope this is of use to some of you and happy coding!

Update
Here is another approach for you. Jim Holmes asked me and Jim Evans how to check if an element is not present, Jim replied with this very neat approach, which could also be used to check if an element is present too. The reason this works is due to the fact that findElements won't throw an exception if non are present, the collection is just empty.

3 comments:

  1. You may be interested in an element-display bug in IEDriver that I uncovered while testing Wikipedia software. It got fixed: https://code.google.com/p/selenium/issues/detail?id=6827

    ReplyDelete
  2. Thank you friend for sharing.

    http://seleniumeasy.com

    ReplyDelete
  3. Thanks for this post, I was in trouble with this command because of the loooong time it takes...
    Btw, there's a little bug on your website ;) Check your //*[@id="HTML1"]/h2 :D
    Cheers

    ReplyDelete