One of the most frequent kind of interactions with the web page when testing with Selenium is checking whether a particular element is present. More specifically, whether it is visible when looking at the page and does not have a "hidden" attribute. The isDisplayed() method is used for such checks, but in many cases it is not used properly. Some tests appear to be unreliable when it comes to checking that the element is displayed, and that is mostly because of the way this method is used. Below are some example of how TO and NOT TO use the method for checking the presence / absence of an element on the page.
When to check that the element is displayed
One thing worth mentioning is that the presence of an element is evaluated in a lazy way, when an interaction with it is attempted, by default (when the element is defined in a Page Object class, by using the @FindBy annotations).
Think about the scenario you want to test. Why are you interested in the presence of an element? Do you need to interact with it in anyway (click on it or get one of its' properties)? If the answer is no (you just need to make sure of the presence of the element), than it's fine to use the isDisplayed method. However if the answer is yes, well think again. Let's analyze the logic a bit: you need to check whether an element is there, actually you need to make sure it is there (the test will fail in case it isn't) and do something with it after you know it's there. You are performing two steps in this case: check the presence of an element, then use it. For this scenario, you are performing one too many steps. When trying to interact with an element, if it is not present, the interaction will result in an error/exception anyhow, so the first step (checking for the presence) is useless. For this case you should remove the first step, and just interact with the element directly. So in the example when you want to click on an element, no need to check whether it is displayed first. Just click on it (and you will basically find out at this step whether it was displayed or not, since its' absence will not make the click possible and an exception will be thrown).
How to test that the element is displayed/not displayed
As mentioned, Selenium provides testers this wonderful method named isDisplayed(). If used properly, this will solve your issue of knowing whether an element is on the page or not.
So what happens when you call isDisplayed on an element? 1. If the element really is visible, the method will return true. 2. If the element is not visible, it will throw an exception. It will NOT return false. This is how this method is implemented within the Selenium library. Therefore, the following pieces of code are not correct:
if (!element.isDisplayed()) {
doSomething();
}
When the element is not displayed, the returned value by isDisplayed is not a boolean, so it cannot be negated. In this example, the doSomething() method, or any other subsequent code, will not be executed if the element is not there.
if (element.isDisplayed()) {
doSomething();
}
else {
doSomethingElse();
}
This last piece of code will only work if the element is displayed. Otherwise, during the evaluation of the isDisplayed code, the exception will be thrown and the 'else' part will not be executed (and neither will be any subsequent code in this test method).
Let's consider some scenarios and the proper way of testing for the presence of elements:
You only want to do something when the element is displayed. When it is not, you don't necessarily care what kind of exception is thrown. In this case, the NoSuchElementException will be thrown, and no further code in the test method will be executed. You don't even need to put an 'if' clause here. If the element will be encountered, the isDisplayed expression will return true, and it will continue the execution of the code with the instruction it has below.
element.isDisplayed()
doSomething();
You want to do something when the element is displayed. When it is not, you want to throw a specific exception, with a detailed message. The exception will stop the rest of the code in the test method from executing.
try {
element.isDisplayed();
doSomething();
}
catch (NoSuchElementException e) {
throw new RuntimeException("This is where you put the message");
}
3. Your element should not be displayed. In case it is, throw an exception. This will stop the rest of the code from running (no point in continuing if a condition is not met). If the element is there, continue executing the rest of the code.
try {
element.isDisplayed();
fail("Element should not have been displayed but it was!");
}
catch (NoSuchElementException e) {}