Skip to content

Commit 906367f

Browse files
committed
Add WebDriverListener example with logging and updated JUnit(pom.xml) config for Windows
- Added example of `WebDriverListener` with logging before `findElement` and `click`. - Included logic to capture screenshots on error for better debugging. - Updated `junit-platform.properties` for Windows compatibility: - forkCount = 0 - junit.jupiter.execution.parallel.config.fixed.parallelism = 1 - junit.jupiter.execution.parallel.config.fixed.max-pool-size = 1 -Run test : mvn clean test -Dtest=WebDriverListenerTest
1 parent 1935ba1 commit 906367f

File tree

4 files changed

+236
-15
lines changed

4 files changed

+236
-15
lines changed

examples/java/pom.xml

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<project xmlns="http://maven.apache.org/POM/4.0.0"
3-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4-
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
55
<modelVersion>4.0.0</modelVersion>
66

77
<groupId>dev.selenium</groupId>
@@ -18,11 +18,11 @@
1818

1919
<repositories>
2020
<repository>
21-
<id>sonatype-nexus-snapshots</id>
22-
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
23-
<snapshots>
24-
<enabled>true</enabled>
25-
</snapshots>
21+
<id>sonatype-nexus-snapshots</id>
22+
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
23+
<snapshots>
24+
<enabled>true</enabled>
25+
</snapshots>
2626
</repository>
2727
</repositories>
2828

@@ -56,19 +56,23 @@
5656
<groupId>org.apache.maven.plugins</groupId>
5757
<artifactId>maven-surefire-plugin</artifactId>
5858
<version>3.5.3</version>
59+
5960
<configuration>
61+
<!-- Fix Error occurred in starting fork, check output in log -->
62+
<forkCount>0</forkCount>
6063
<properties>
61-
<configurationParameters>
62-
junit.jupiter.execution.parallel.enabled = true
64+
<configurationParameters> junit.jupiter.execution.parallel.enabled = true
6365
junit.jupiter.execution.parallel.mode.default = concurrent
64-
junit.jupiter.execution.parallel.config.strategy = fixed
65-
junit.jupiter.execution.parallel.config.fixed.parallelism = ${surefire.parallel}
66-
junit.jupiter.execution.parallel.config.fixed.max-pool-size = ${surefire.parallel}
67-
</configurationParameters>
66+
junit.jupiter.execution.parallel.config.strategy = fixed <!-- Fix Failed
67+
to transform configuration parameter with key
68+
'junit.jupiter.execution.parallel.config.fixed.parallelism' and initial
69+
value ' -->
70+
junit.jupiter.execution.parallel.config.fixed.parallelism = 1
71+
junit.jupiter.execution.parallel.config.fixed.max-pool-size = 1 </configurationParameters>
6872
</properties>
6973
<rerunFailingTestsCount>3</rerunFailingTestsCount>
7074
</configuration>
7175
</plugin>
7276
</plugins>
7377
</build>
74-
</project>
78+
</project>
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
package dev.selenium.listeners;
2+
3+
import org.openqa.selenium.*;
4+
import org.openqa.selenium.remote.RemoteWebDriver;
5+
import org.openqa.selenium.support.events.WebDriverListener;
6+
7+
import java.io.File;
8+
import java.io.IOException;
9+
import java.lang.reflect.InvocationTargetException;
10+
import java.lang.reflect.Method;
11+
import java.nio.file.Files;
12+
import java.nio.file.Paths;
13+
import java.text.SimpleDateFormat;
14+
import java.util.Date;
15+
import java.util.List;
16+
import java.util.logging.Level;
17+
import java.util.logging.Logger;
18+
19+
public class CustomWebDriverListener implements WebDriverListener {
20+
21+
private static final Logger logger = Logger.getLogger(CustomWebDriverListener.class.getName());
22+
// Link refe color https://gist.github.com/dainkaplan/4651352
23+
24+
private static final String RESET = "\u001B[0m";
25+
private static final String GREEN = "\u001B[32m";
26+
27+
private String formatArgs(Object[] args) {
28+
if (args == null || args.length == 0)
29+
return "[]";
30+
StringBuilder sb = new StringBuilder("[");
31+
for (Object arg : args) {
32+
sb.append(arg).append(", ");
33+
}
34+
if (sb.length() > 1)
35+
sb.setLength(sb.length() - 2);
36+
sb.append("]");
37+
return sb.toString();
38+
}
39+
40+
private String getDriverInfo(WebDriver driver) {
41+
if (driver instanceof RemoteWebDriver remoteDriver) {
42+
Capabilities caps = remoteDriver.getCapabilities();
43+
String sessionId = remoteDriver.getSessionId().toString();
44+
return String.format("Browser: %s, Version: %s, Platform: %s, SessionId: %s",
45+
caps.getBrowserName(),
46+
caps.getBrowserVersion(),
47+
caps.getPlatformName(),
48+
sessionId);
49+
} else {
50+
return "Unknown WebDriver instance";
51+
}
52+
}
53+
54+
private String getElementInfo(WebElement element) {
55+
try {
56+
return element.toString().replaceAll(".*-> ", "").replaceAll("]", "");
57+
} catch (Exception e) {
58+
return "Unknown Element";
59+
}
60+
}
61+
62+
// -- WebDriver call hooks --
63+
64+
@Override
65+
public void beforeAnyWebDriverCall(WebDriver driver, Method method, Object[] args) {
66+
logger.info("BEFORE: Driver: " + GREEN + driver + RESET + ", Method: " + method.getName() + ", Args: "
67+
+ formatArgs(args));
68+
}
69+
70+
@Override
71+
public void afterAnyWebDriverCall(WebDriver driver, Method method, Object[] args, Object result) {
72+
logger.info("AFTER: Driver: " + GREEN + driver + RESET + ", Method: " + method.getName() +
73+
", Args: " + formatArgs(args) + ", Result: " + result);
74+
}
75+
76+
// -- Click hooks --
77+
78+
@Override
79+
public void beforeClick(WebElement element) {
80+
logger.info("BEFORE click -> Element: " + getElementInfo(element));
81+
}
82+
83+
@Override
84+
public void afterClick(WebElement element) {
85+
logger.info("AFTER click -> Element: " + getElementInfo(element));
86+
}
87+
88+
// -- FindElement hooks --
89+
90+
@Override
91+
public void beforeFindElement(WebDriver driver, By locator) {
92+
logger.info("BEFORE findElement -> Locator: " + locator);
93+
try {
94+
if (driver instanceof HasCapabilities) {
95+
List<WebElement> elements = driver.findElements(locator);
96+
logger.info("DEBUG: Number of elements matching '" + locator + "': " + elements.size());
97+
}
98+
} catch (Exception e) {
99+
logger.warning("Error while counting elements for locator " + locator + ": " + e.getMessage());
100+
}
101+
}
102+
103+
@Override
104+
public void afterFindElement(WebDriver driver, By locator, WebElement result) {
105+
logger.info("AFTER findElement -> Locator: " + locator + ", Result: " + getElementInfo(result));
106+
}
107+
108+
@Override
109+
public void beforeFindElements(WebDriver driver, By locator) {
110+
logger.info("BEFORE findElements -> Locator: " + locator);
111+
try {
112+
if (driver instanceof HasCapabilities) {
113+
List<WebElement> elements = driver.findElements(locator);
114+
logger.info("DEBUG: Number of elements matching '" + locator + "': " + elements.size());
115+
}
116+
} catch (Exception e) {
117+
logger.warning("Error while counting elements for locator " + locator + ": " + e.getMessage());
118+
}
119+
}
120+
121+
@Override
122+
public void afterFindElements(WebDriver driver, By locator, List<WebElement> elements) {
123+
logger.info("AFTER findElements -> Locator: " + locator + ", Elements found: " + elements.size());
124+
}
125+
126+
@Override
127+
public void onError(Object target, Method method, Object[] args, InvocationTargetException e) {
128+
logger.log(Level.SEVERE, "Exception in method '" + method.getName() + "': " + e.getCause(), e);
129+
takeScreenshotOnError(target, method.getName());
130+
}
131+
132+
private void takeScreenshotOnError(Object target, String methodName) {
133+
if (target instanceof TakesScreenshot) {
134+
try {
135+
String directoryPath = "images";
136+
File directory = new File(directoryPath);
137+
if (!directory.exists()) {
138+
directory.mkdirs();
139+
}
140+
141+
File screenshot = ((TakesScreenshot) target).getScreenshotAs(OutputType.FILE);
142+
String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
143+
String fileName = directoryPath + File.separator + "screenshot_error_" + methodName + "_" + timestamp
144+
+ ".png";
145+
Files.copy(screenshot.toPath(), Paths.get(fileName));
146+
147+
logger.info(GREEN + "Screenshot saved: " + fileName);
148+
} catch (IOException ioException) {
149+
logger.severe("Failed to save screenshot: " + ioException.getMessage());
150+
} catch (Exception ex) {
151+
logger.severe("Unexpected error during screenshot capture: " + ex.getMessage());
152+
}
153+
} else {
154+
logger.info("Target does not support screenshots.");
155+
}
156+
}
157+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package dev.selenium.listeners;
2+
3+
import org.junit.jupiter.api.*;
4+
import org.openqa.selenium.*;
5+
import org.openqa.selenium.chrome.ChromeDriver;
6+
import org.openqa.selenium.support.events.EventFiringDecorator;
7+
import org.openqa.selenium.support.events.WebDriverListener;
8+
import org.slf4j.Logger;
9+
import org.slf4j.LoggerFactory;
10+
11+
import java.io.File;
12+
import java.io.IOException;
13+
import java.lang.reflect.InvocationTargetException;
14+
import java.nio.file.Files;
15+
import java.nio.file.Paths;
16+
import java.text.SimpleDateFormat;
17+
import java.util.Date;
18+
import java.util.List;
19+
20+
public class WebDriverListenerTest {
21+
22+
private WebDriver driver;
23+
24+
@Test
25+
@Order(1)
26+
public void testWebDriverListener() {
27+
WebDriverListener listener = new CustomWebDriverListener();
28+
driver = new EventFiringDecorator<>(listener).decorate(new ChromeDriver());
29+
30+
driver.get("https://www.selenium.dev/");
31+
driver.manage().window().maximize();
32+
33+
WebElement documentation = driver.findElement(By.cssSelector("a[href='/documentation']"));
34+
35+
documentation.click();
36+
37+
driver.quit();
38+
39+
}
40+
41+
@Test
42+
@Order(2)
43+
public void testWebDriverListenerOnError() {
44+
WebDriverListener listener = new CustomWebDriverListener();
45+
driver = new EventFiringDecorator<>(listener).decorate(new ChromeDriver());
46+
47+
try {
48+
driver.get(null);
49+
} catch (NullPointerException e) {
50+
e.printStackTrace();
51+
}
52+
53+
driver.quit();
54+
55+
}
56+
57+
}

website_and_docs/content/documentation/webdriver/support_features/listeners.en.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,12 @@ aliases: [
1010
These allow you to execute custom actions in every time specific Selenium commands are sent
1111

1212
{{< tabpane text=true >}}
13+
1314
{{< tab header="Java" >}}
14-
{{< badge-code >}}
15+
{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/listeners/WebDriverListenerTest.java#L24-L40" >}}
1516
{{< /tab >}}
17+
18+
1619
{{% tab header="Python" %}}
1720
{{< badge-code >}}
1821
{{% /tab %}}

0 commit comments

Comments
 (0)