Skip to content

Add WebDriverListener example with logging #2384

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: trunk
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 14 additions & 13 deletions examples/java/pom.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>dev.selenium</groupId>
Expand All @@ -18,11 +18,11 @@

<repositories>
<repository>
<id>sonatype-nexus-snapshots</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
<id>sonatype-nexus-snapshots</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>

Expand Down Expand Up @@ -56,15 +56,16 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.5.3</version>

<configuration>
<!-- Fix Error occurred in starting fork, check output in log -->
<forkCount>0</forkCount>
<properties>
<configurationParameters>
junit.jupiter.execution.parallel.enabled = true
<configurationParameters> junit.jupiter.execution.parallel.enabled = true
junit.jupiter.execution.parallel.mode.default = concurrent
junit.jupiter.execution.parallel.config.strategy = fixed
junit.jupiter.execution.parallel.config.fixed.parallelism = ${surefire.parallel}
junit.jupiter.execution.parallel.config.fixed.max-pool-size = ${surefire.parallel}
</configurationParameters>
junit.jupiter.execution.parallel.config.strategy = fixed
junit.jupiter.execution.parallel.config.fixed.parallelism = 1
junit.jupiter.execution.parallel.config.fixed.max-pool-size = 1 </configurationParameters>
</properties>
<rerunFailingTestsCount>3</rerunFailingTestsCount>
</configuration>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
package dev.selenium.listeners;

import org.openqa.selenium.*;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.support.events.WebDriverListener;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

public class CustomWebDriverListener implements WebDriverListener {

private static final Logger logger = Logger.getLogger(CustomWebDriverListener.class.getName());
// Link refe color https://gist.github.com/dainkaplan/4651352

private static final String RESET = "\u001B[0m";
private static final String GREEN = "\u001B[32m";

private String formatArgs(Object[] args) {
if (args == null || args.length == 0)
return "[]";
StringBuilder sb = new StringBuilder("[");
for (Object arg : args) {
sb.append(arg).append(", ");
}
if (sb.length() > 1)
sb.setLength(sb.length() - 2);
sb.append("]");
return sb.toString();
}

private String getDriverInfo(WebDriver driver) {
if (driver instanceof RemoteWebDriver remoteDriver) {
Capabilities caps = remoteDriver.getCapabilities();
String sessionId = remoteDriver.getSessionId().toString();
return String.format("Browser: %s, Version: %s, Platform: %s, SessionId: %s",
caps.getBrowserName(),
caps.getBrowserVersion(),
caps.getPlatformName(),
sessionId);
} else {
return "Unknown WebDriver instance";
}
}

private String getElementInfo(WebElement element) {
try {
return element.toString().replaceAll(".*-> ", "").replaceAll("]", "");
} catch (Exception e) {
return "Unknown Element";
}
}

// -- WebDriver call hooks --

@Override
public void beforeAnyWebDriverCall(WebDriver driver, Method method, Object[] args) {
logger.info("BEFORE: Driver: " + GREEN + driver + RESET + ", Method: " + method.getName() + ", Args: "
+ formatArgs(args));
}

@Override
public void afterAnyWebDriverCall(WebDriver driver, Method method, Object[] args, Object result) {
logger.info("AFTER: Driver: " + GREEN + driver + RESET + ", Method: " + method.getName() +
", Args: " + formatArgs(args) + ", Result: " + result);
}

// -- Click hooks --

@Override
public void beforeClick(WebElement element) {
logger.info("BEFORE click -> Element: " + getElementInfo(element));
}

@Override
public void afterClick(WebElement element) {
logger.info("AFTER click -> Element: " + getElementInfo(element));
}

// -- FindElement hooks --


@Override
public void afterFindElement(WebDriver driver, By locator, WebElement result) {
logger.info("AFTER findElement -> Locator: " + locator + ", Result: " + getElementInfo(result));
}

@Override
public void beforeFindElements(WebDriver driver, By locator) {
logger.info("BEFORE findElements -> Locator: " + locator);
try {
if (driver instanceof HasCapabilities) {
List<WebElement> elements = driver.findElements(locator);
logger.info("DEBUG: Number of elements matching '" + locator + "': " + elements.size());
}
} catch (Exception e) {
logger.warning("Error while counting elements for locator " + locator + ": " + e.getMessage());
}
}

@Override
public void afterFindElements(WebDriver driver, By locator, List<WebElement> elements) {
logger.info("AFTER findElements -> Locator: " + locator + ", Elements found: " + elements.size());
}

@Override
public void onError(Object target, Method method, Object[] args, InvocationTargetException e) {
logger.log(Level.SEVERE, "Exception in method '" + method.getName() + "': " + e.getCause(), e);
takeScreenshotOnError(target, method.getName());
}

private void takeScreenshotOnError(Object target, String methodName) {
if (target instanceof TakesScreenshot) {
try {
String directoryPath = "images";
File directory = new File(directoryPath);
if (!directory.exists()) {
directory.mkdirs();
}

File screenshot = ((TakesScreenshot) target).getScreenshotAs(OutputType.FILE);
String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String fileName = directoryPath + File.separator + "screenshot_error_" + methodName + "_" + timestamp
+ ".png";
Files.copy(screenshot.toPath(), Paths.get(fileName));

logger.info(GREEN + "Screenshot saved: " + fileName);
} catch (IOException ioException) {
logger.severe("Failed to save screenshot: " + ioException.getMessage());
} catch (Exception ex) {
logger.severe("Unexpected error during screenshot capture: " + ex.getMessage());
}
} else {
logger.info("Target does not support screenshots.");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package dev.selenium.listeners;

import org.junit.jupiter.api.*;
import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.events.EventFiringDecorator;
import org.openqa.selenium.support.events.WebDriverListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

public class WebDriverListenerTest {

private WebDriver driver;

@Test
@Order(1)
public void testWebDriverListener() {
WebDriverListener listener = new CustomWebDriverListener();
driver = new EventFiringDecorator<>(listener).decorate(new ChromeDriver());

driver.get("https://www.selenium.dev/");
driver.manage().window().maximize();

WebElement documentation = driver.findElement(By.cssSelector("a[href='/documentation']"));

documentation.click();

driver.quit();

}

@Test
@Order(2)
public void testWebDriverListenerOnError() {
WebDriverListener listener = new CustomWebDriverListener();
driver = new EventFiringDecorator<>(listener).decorate(new ChromeDriver());

try {
driver.get(null);
} catch (NullPointerException e) {
e.printStackTrace();
}

driver.quit();

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,12 @@ aliases: [
These allow you to execute custom actions in every time specific Selenium commands are sent

{{< tabpane text=true >}}

{{< tab header="Java" >}}
{{< badge-code >}}
{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/listeners/WebDriverListenerTest.java#L24-L40" >}}
{{< /tab >}}


{{% tab header="Python" %}}
{{< badge-code >}}
{{% /tab %}}
Expand Down