3

I am using serenity BDD for my automation testing and Page Object Model for my framework. I have created a BasePage class which will be inherited by all the other Pages. I want to minimize the logging messages from the Pages by adding all the log.info messages to a central Base page. Example, when calling the click() method, I will log before click and after click methods as shown below in the basePage class:

public class BasePage extends PageObject{

private static final Logger log = LogManager.getLogger(BasePage.class.getClass());
private final WebElementFacade element;

public static void clickBtn(WebElementFacade btnName) {
        log.info("About to click " + btnName + " button");
        btnName.click();
        log.info("Successfully clicked on " + btnName + " button.");        
    }

Later I figured that instead of individually trying to figure out in advance what actions the user will perform on the webElements, and write new methods for each action (like the one shown above), just implement WebDriverFacade interface, so that I get all the unimplemented method list in BasePage from WebDriverFacade and then write the log messages inside each of them, like so:

public class BasePage extends PageObject implements WebElementFacade{

private static final Logger log = LogManager.getLogger(BasePage.class.getClass());
private final WebElementFacade element;

@Override
public void submit() {
    // TODO Auto-generated method stub
    
}

@Override
public void sendKeys(CharSequence... keysToSend) {
    // TODO Auto-generated method stub
    
}

@Override
public String getTagName() {
    // TODO Auto-generated method stub
    return null;
}

@Override
public boolean isSelected() {
    // TODO Auto-generated method stub
    return false;
}
        .
        .
        .
        .
        .
}

This will serve two purposes:

I will not have to create new methods for every action in BasePage class, example the 'clickBtn()' function in the first code As I mentioned before, I will not have to figure out what method any other person who adds methods to my code might use and having to change the BasePage class to create the new actions. So basically less maintenance in the long run. The problem I am facing is an error that I receive in the second use case:

The return types are incompatible for the inherited methods WebElementFacade.withTimeoutOf(int, TimeUnit), PageObject.withTimeoutOf(int, TimeUnit)

Now my question is:

How can solve this problem? Is this the right way to do things or should I be going with the first method and have maintenance overhead. Thank you!

2

You should not implement WebElementFacade. Selenium supplies EventFiringWebDriver for such purpose. Using it you can add actions to take before and/or after any method WebDriver or WebElement provides.

So you substitute your webdriver with that event-driven wrapper in the way like this:

@BeforeEach
public void setUp(){
    driver = new FirefoxDriver();
    EventFiringWebDriver eventFiringWebDriver = new EventFiringWebDriver(driver);
    eventFiringWebDriver.register(new CustomLoggingListener());
    driver = eventFiringWebDriver;
}

Where CustomLoggingListener in this example extends AbstractWebDriverEventListener (which is also a part of Selenium package) and sets the required actions to take (e.g. log actions).

Like this:

public class CustomLoggingListener extends AbstractWebDriverEventListener {


    @Override
    public void beforeClickOn(WebElement element, WebDriver driver) {
        String messageId = UUID.randomUUID().toString();
        System.out.println(messageId + " : Clicking element [" + element + "] with driver [" + driver + "]");
    }

    @Override
    public void afterClickOn(WebElement element, WebDriver driver) {
        String messageId = UUID.randomUUID().toString();
        System.out.println(messageId + " : Clicked element [" + element + "] with driver [" + driver + "]");
    }

}

Here you can find more detailed example of how to add logging functionality (including taking screenshot at any step) to tests framework which already exists.

1
  • Thank you Alexey. A question though. can EventFiringWebDriver be used with WebElementFacade from serenity bdd? The webdriverfacade provides many useful checks before webelement actions take place. Like waiting for the element to appear and be enabled. That makes my work really easier and neat. WebElementFacade is basically a wrapper over WebElement. So knowing this, how can i use eventfiringwebdriver with webelementfacade? – Suhas May 1 at 4:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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