1

I use selendroid in order to test an hybrid application. I have my own logger which logs and also use WebDriverWait to wait for specific behavior. My question is how can I use my logger before WebDriverWait is failed and throws timeoutException?

Erki M.
  • 5,022
  • 1
  • 48
  • 74
galvan
  • 7,400
  • 7
  • 38
  • 55

2 Answers2

1

First, I know nothing about selendroid.

A simple solution could be:

public void waitForCondition(WebElement element){
    try{
        new WebDriverWait(driver, 60)
                .until(ExpectedConditions.visibilityOf(element)); // your condition
    } catch (TimeoutException e){
        // do log or whatever
    }
}

Anyway, You usually do this by implementing WebDriverEventListener and register this with EventFiringWebDriver, then invoke it something like:

EventFiringWebDriver eventFiringWebDriver = new EventFiringWebDriver(new FirefoxDriver());
MyWebDriverEventListener listener = new MyWebDriverEventListener();
eventFiringWebDriver.register(listener);

where MyWebDriverEventListener is something like

class MyWebDriverEventListener implements WebDriverEventListener {
            // .. skipped
}

So, basically what WebDriverWait's until method is doing, is that it is executing the driver.findElement until:

Repeatedly applies this instance's input value to the given function until one of the following occurs:

  • the function returns neither null nor false,
  • the function throws an unignored exception,
  • the timeout expires,
  • the current thread is interrupted

So what you could do, is implement your logging in WebDriverEventListener

public void afterFindBy(By by, WebElement element, WebDriver driver) {
    // Do logging 
}

This would be applyed every time element is found (not only wait, but regular driver.findElement also). Anyway, this does not cover the case when exception is thrown. You also have a chance to log in onException method, using something like

if (throwable instanceof TimeoutException){
    // log
}

I would not do it but it's your code.

That being said, I usually don't do this because I do not care about such verbose log level, I just have 2 helper methods that can take care of all the waits I ever need:

public void waitUntil(WebElement element) {
    new WebDriverWait(driver, 60)
            .ignoring(NoSuchElementException.class)
            .ignoring(StaleElementReferenceException.class)
            .until(ExpectedConditions.visibilityOf(element));
}

public void waitUntil(List<WebElement> elements) {
    new WebDriverWait(driver, 60)
            .ignoring(NoSuchElementException.class)
            .ignoring(StaleElementReferenceException.class)
            .until(ExpectedConditions.visibilityOfAllElements(elements));
}

It would be trivial to add logging there.


Edit: i have following solution working:

public class Demo {

    @Test
    public void testEventFire(){
        EventFiringWebDriver firingWebDriver = new EventFiringWebDriver(new FirefoxDriver());
        firingWebDriver.register(new MyListener());
        try {
            firingWebDriver.navigate().to(new URL("http://www.google.com"));
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
    }

    private static class MyListener extends AbstractWebDriverEventListener {
        @Override
        public void beforeNavigateTo(String url, WebDriver driver) {
            System.out.println("beforeNavigateTo");
        }

    }
Erki M.
  • 5,022
  • 1
  • 48
  • 74
  • I tried the solution using EventFiringWebDriver using the following code: driver = new SelendroidDriver(caps); EventFiringWebDriver eventFiringWebDriver = new EventFiringWebDriver(driver); eventFiringWebDriver.register(new MyWebDriverEventListener()); where MyWebDriverEventListener is listener as in your answer. Actually I don't see any logs, do you know what can be the problem? – galvan Aug 17 '14 at 08:38
  • Actually not. I put System.out.println in every callback and it looks like the code don't reach any of them – galvan Aug 17 '14 at 15:05
  • check my edit. If it is not working, it might be an issue with selendroid. – Erki M. Aug 18 '14 at 06:22
0

There is a Message property of WebDriverWait which you may set your failure message.

It is a good idea to wrap a Wait function in a static class like this (you may avoid creating the WebDriverWait object all the time) and set the Message:

private static IWebDriver activeDriver;
private static WebDriverWait activeWait;
public static WebDriverWait Wait(this IWebDriver driver, string message = "Test has timed out while finding a UI element")
{
    if (driver != activeDriver)
    {
        activeDriver = driver;
        try
        {
            activeWait = new WebDriverWait(driver, timeout);
        }
        catch (Exception)
        {
            throw Exception(message);
        }
    }
    activeWait.Message = message;

    return activeWait;
}

To call the Wait wrapper above (since it is written as an extension method):

YourDriverObject.Wait("Your failure message").Until(ExpectedConditions);

If you want the simplest form (without wrapping etc.):

var webDriverWait = new WebDriverWait(driver, timeout);
webDriverWait.Message = "Your message when exception is thrown";
erenalgan
  • 60
  • 1
  • 7