16

I am using selenium web driver and appium as this is mobile application automation,

I am trying to check that if element is there or not and based on that I have put conditions.

 long starttime = System.currentTimeMillis();
 long endtime = starttime + 60*1000; // 60 seconds * 1000 ms/sec;


while(System.currentTimeMillis() < endtime)
{

    notcount = driver.findElement(By.id(AppConstants.notificationcount));

}

if(notcount.equals(null))

{

    System.out.println("No Element found");
}
else
{

    //SOME ANOTHER STEPS
}

Here issue is when element is not there , instead to redirect to ELSE part , selenium stops execution and throwing exception.

I do not want to use List -findelements here as that is taking long time to find element.

1
  • 1
    I googled for "selenium wait and if not found do something" first two hits had the solution :) See my answer. Aug 7, 2015 at 12:01

8 Answers 8

27

Use findElements instead of findElement.

findElements will return an empty list if no matching elements are found instead of an exception.

To check that an element is present, you could try this

Boolean isPresent = driver.findElements(By.yourLocator).size() > 0

This will return true if at least one element is found and false if it does not exist.

Text copied from: https://stackoverflow.com/questions/7991522/selenium-webdriver-test-if-element-is-present

Another posbility is to use a Try/Catch construction, see this for more info: https://stackoverflow.com/questions/6521270/webdriver-check-if-an-element-exists

4
  • Yes I agree and already tried this solution but it takes long time to search element even if element is not there and that's why I have mentioned that I do not want to use LIST or findelements for this. Aug 10, 2015 at 2:59
  • Use the try/catch construction instead then. But how much longer does it really take? Wouldn't except to much, unless your finding hundreds of elements. Also I wonder if your really want to continue the test if an element cannot be found, why are you looking for it then? Let the test fail. Aug 10, 2015 at 6:40
  • I am also surprised that I am finding only 1 element and for that only webdriver is taking long time. I want test continue in manner like if element not found then go to ELSE part.. Aug 10, 2015 at 7:12
  • 3
    Having if/then/else constructs in the test is an anti-pattern to me. The test should describe one execution path and avoid any logic. If something blocks this execution path, then fail fast, as suggested. If you want to cover multiple execution paths then create multiple tests where each covers one execution path.
    – dzieciou
    Aug 19, 2015 at 5:35
6

What you are experiencing is a fast-fail type of behavior when you use .findElement . You don't really need to use .findElements(el) to get a soft-fail behavior. What you could do is something like this instead:

protected void checkElementPresence(final WebDriver driver,final By by,final String errorMsg){
  new WebDriverWaitWithMessage(driver,10).failWith(errorMsg).until(new ExpectedCondition<Boolean>(){
    @Override public Boolean apply(    WebDriver webDriver){
      try {
        return driver.findElement(by).isDisplayed();
      }
 catch (      NoSuchElementException ignored) {
        return false;
      }
catch (      StaleElementReferenceException ignored) {
        return false;
      }
    }
  }
);

But requires this support class:

protected static class WebDriverWaitWithMessage extends WebDriverWait {

        private String message;

        public WebDriverWaitWithMessage(WebDriver driver, long timeOutInSeconds) {
            super(driver, timeOutInSeconds);
        }

        public WebDriverWait failWith(String message) {
            if (message == null || message.length() == 0) {
                throw new IllegalArgumentException("Error message must not be null nor empty");
            }
            this.message = message;
            return this;
        }

        @Override
        public <V> V until(Function<? super WebDriver, V> isTrue) {
            if (message == null) {
                return super.until(isTrue);
            } else {
                try {
                    return super.until(isTrue);
                } catch (TimeoutException e) {
                    throw new TimeoutException(message, e);
                }
            }
        }
    }
2

(note I haven't tried this in java, but this is how to do it in C#)

You should place the findelement in a try/catch block, so that if the element is not found you can catch the exception and do the correct thing.

It would look something like this:

try
{
    driver.FindElement(By.CssSelector("selector"));
} 
catch(NoSuchElementException)
{
    Console.WriteLine("Element does not exist!");
} 

Edit:
I will note that it looks like you are trying to implement your own webdriver wait behavior, so maybe look into the first answer here: https://stackoverflow.com/questions/11736027/webdriver-wait-for-element which explains how to wait for elements with explicit waits in Java.

1

Use Exception handling block for that line of codes. try { } catch { } finally { } If the element is not found then it execute the codes in the finally block and continue to other lines of code

1
  • 1
    Please expand on your answer to explain how it improves on the existing answers - particularly the accepted answer.
    – Kate Paulk
    Dec 13, 2017 at 12:18
0
public void sellProduct(){                          

            try {
                for(int i=0; i< 5 ;i++){
                    try {
                        if(!driver.findElements(By.xpath("/html/body/div[@class='container']/table[@class='table table-striped'][2]/tbody[@id='bought']/tr[@id="+i+"]/th[4]/button")).isEmpty())            {
                            try {
                                driver.findElement(By.xpath("/html/body/div[@class='container']/table[@class='table table-striped'][2]/tbody[@id='bought']/tr[@id="+i+"]/th[4]/button")).click();
                            } catch (NoSuchElementException e) {
                                e.printStackTrace();
                            }
                        }

                        else{
                            try {
                                System.out.println("no products to sell ");
                            } catch (NoSuchElementException e) {
                                e.printStackTrace();
                            }
                        }
                    } catch (NoSuchElementException e) {
                        e.printStackTrace();
                    }

                }
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

I wrote this code but keep on getting the issue target widow is already closed, I want the loop to exit when there is no web element found.

1
  • Does the accepted answer to this question help you? If not, please post this as its own question and explain why the accepted answer here is not helping. Please do not post "I'm having the same question" as an answer - your post is likely to be deleted.
    – Kate Paulk
    Jan 24, 2018 at 16:53
0

I use C# but this is the method I use:

/// <summary>
    /// Looks to see if the passed in element is on the webpage or not. Returns true or false.
    /// </summary>
    /// <param name="by"></param>
    /// <param name="element"></param>
    /// <param name="driver"></param>
    /// <returns></returns>
    public static bool tryToFindElement(By by, out IWebElement element, IWebDriver driver)
    {
        try
        {
            element = driver.FindElement(by);
        }
        catch (NoSuchElementException)
        {
            element = null;
            return false;
        }
        return true;
    }

    /// <summary>
    /// Checks to see if the web element is displayed and enabled.
    /// </summary>
    /// <param name="element"></param>
    /// <returns></returns>
    public static bool isElementVisible(IWebElement element)
    {
        return element.Displayed && element.Enabled;
    }

I call it like this:

if (tryToFindElement(By.CssSelector("<CSS Selector>"), out element, driver))
                {
                    bool visible = isElementVisible(element);
                    if (visible == true)
                    {
                     //Do something
                    }
                }
0

I have tried answer of getting boolean response but as i see that could be possible only when we have set driver's timeout.

I had timeout of 20 sec and i was following above accepted answer.

So instead of only checking boolean isPresesnt = driver.findElements(by).size() > 0; I would rather suggest, additionally you must set implicit timeout for driver.

driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);

Hope this helps!!

-1

Simply set the time to search for an element to implicitly short time this will cause the list to come back as null

androidDriver.manage().timeouts().implicitlyWait(2, TimeUnit.SECONDS);
List<AndroidElement> yesterdaysImage = androidDriver.findElementsById("MOBILE_PACKAGE_NAME:id/goals_item_yesterday");

(I know this is Selenium and I posted Appium, but Appium is derived from Selenium so this code is still valid)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.