Skip to content

Refactor java examples#2570

Merged
diemol merged 4 commits intoSeleniumHQ:trunkfrom
asolntsev:refactor/java-examples
Jan 23, 2026
Merged

Refactor java examples#2570
diemol merged 4 commits intoSeleniumHQ:trunkfrom
asolntsev:refactor/java-examples

Conversation

@asolntsev
Copy link
Contributor

@asolntsev asolntsev commented Jan 21, 2026

User description

Description

fix IDEA setup for Java project

  • update JUnit and Selenium dependencies
  • add missing dependencies to Gradle script
  • add IDEA- and Gradle- specific files to .gitignore

fix closing WebDriver after tests

  • always wrap driver.quit() into if (driver != null) to avoid NPE if the browser hadn't been started due to some error
  • mark the closing @AfterEach method as final to avoid occasional overriding in subclasses
  • No need to call driver.quit() in BaseTest subclasses because it's already done by BaseTest.

Motivation and Context

Avoid spreading typical errors. First of all, this bad method:

	@AfterEach
	public void teardown() {
		driver.quit();
	}

it will cause NPE if the driver hadn't even been started (due to some previous error).

Types of changes

  • Change to the site (I have double-checked the Netlify deployment, and my changes look good)
  • Code example added (and I also added the example to all translated languages)
  • Improved translation
  • Added new translation (and I also added a notice to each document missing translation)

Checklist

  • I have read the contributing document.
  • [] I have used hugo to render the site/docs locally and I am sure it works.

PR Type

Enhancement, Bug fix


Description

  • Update Selenium and JUnit dependencies to latest versions

  • Refactor WebDriver cleanup to prevent NPE and improve code consistency

    • Wrap driver.quit() with null checks in all test classes
    • Mark cleanup methods as final to prevent overriding
    • Remove redundant driver.quit() calls from individual test methods
  • Improve code formatting and style consistency across test files

  • Add missing test scope to selenium-logger dependency


Diagram Walkthrough

flowchart LR
  A["Dependency Updates"] --> B["pom.xml"]
  C["WebDriver Cleanup Refactor"] --> D["BaseTest.java"]
  D --> E["Test Classes"]
  F["Code Formatting"] --> E
  G["Null Safety"] --> D
  style A fill:#e1f5ff
  style C fill:#fff3e0
  style F fill:#f3e5f5
Loading

File Walkthrough

Relevant files
Dependencies
1 files
pom.xml
Update Selenium and JUnit dependencies                                     
+3/-2     
Bug fix
5 files
BaseTest.java
Refactor cleanup method with null checks and final modifier
+3/-7     
SingleInstanceCookieParallelTest.java
Add null check to driver cleanup in AfterAll                         
+4/-1     
FirefoxTest.java
Add null checks and remove redundant quit calls                   
+6/-13   
UsingSeleniumTest.java
Add null check and final modifier to teardown method         
+4/-2     
CookiesTest.java
Centralize driver cleanup with AfterEach and fix formatting
+83/-88 
Enhancement
4 files
EdgeTest.java
Remove redundant driver.quit() call from test method         
+0/-1     
HttpClientTest.java
Remove redundant driver.quit() calls from test methods     
+0/-3     
AlertsTest.java
Remove redundant endSession cleanup method                             
+0/-5     
InteractionsTest.java
Remove try-finally blocks and rely on base class cleanup 
+13/-22 
Formatting
2 files
InformationTest.java
Fix indentation and formatting consistency                             
+41/-40 
PrintsPageTest.java
Remove unused import statement                                                     
+0/-1     

* update JUnit and Selenium dependencies
* add missing dependencies to Gradle script
* add IDEA- and Gradle- specific files to .gitignore
* always wrap `driver.quit()` into `if (driver != null)` to avoid NPE if the browser hadn't been started due to some error
* mark the closing @AfterEach method as final to avoid occasional overriding in subclasses
* No need to call `driver.quit()` in `BaseTest` subclasses because it's already done by `BaseTest`.
@netlify
Copy link

netlify bot commented Jan 21, 2026

Deploy Preview for selenium-dev ready!

Name Link
🔨 Latest commit 4ab09ee
🔍 Latest deploy log https://app.netlify.com/projects/selenium-dev/deploys/697340fb6a12540008feb150
😎 Deploy Preview https://deploy-preview-2570--selenium-dev.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@qodo-code-review
Copy link
Contributor

qodo-code-review bot commented Jan 21, 2026

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
Hardcoded credentials

Description: The test code hardcodes credentials (admin / myStrongPassword) and also embeds them into a
URL via embedAuthToUrl(...), which risks accidental credential exposure through logs,
stack traces, proxies, or version control reuse.
HttpClientTest.java [36-90]

Referred Code
public void remoteWebDriverWithClientConfig() throws Exception {
    ClientConfig clientConfig = ClientConfig.defaultConfig()
            .withRetries()
            .sslContext(createSSLContextWithCA(Path.of("src/test/resources/tls.crt").toAbsolutePath().toString()))
            .connectionTimeout(Duration.ofSeconds(300))
            .readTimeout(Duration.ofSeconds(3600))
            .authenticateAs(new UsernameAndPassword("admin", "myStrongPassword"))
            .version(HTTP_1_1.toString());
    ChromeOptions options = getDefaultChromeOptions();
    options.setEnableDownloads(true);
    driver = RemoteWebDriver.builder()
            .oneOf(options)
            .address(gridUrl)
            .config(clientConfig)
            .build();
}

@Test
public void remoteWebDriverIgnoreSSL() throws Exception {
    ClientConfig clientConfig = ClientConfig.defaultConfig()
            .withRetries()


 ... (clipped 34 lines)
TLS verification disabled

Description: The remoteWebDriverIgnoreSSL setup uses an SSL context that ignores certificate validation
(createIgnoreSSLContext()), enabling man-in-the-middle attacks if similar configuration is
reused beyond test environments.
HttpClientTest.java [54-69]

Referred Code
public void remoteWebDriverIgnoreSSL() throws Exception {
    ClientConfig clientConfig = ClientConfig.defaultConfig()
            .withRetries()
            .sslContext(createIgnoreSSLContext())
            .connectionTimeout(Duration.ofSeconds(300))
            .readTimeout(Duration.ofSeconds(3600))
            .authenticateAs(new UsernameAndPassword("admin", "myStrongPassword"))
            .version(HTTP_1_1.toString());
    ChromeOptions options = getDefaultChromeOptions();
    options.setEnableDownloads(true);
    driver = RemoteWebDriver.builder()
            .oneOf(options)
            .address(gridUrl)
            .config(clientConfig)
            .build();
}
Browser sandbox disabled

Description: Default browser options add --no-sandbox for Chrome and Edge, which weakens browser
process isolation and can increase impact of browser/renderer compromise if these defaults
are used in less-isolated environments.
BaseTest.java [61-67]

Referred Code
protected static ChromeOptions getDefaultChromeOptions() {
    return new ChromeOptions().addArguments("--no-sandbox");
}

protected static EdgeOptions getDefaultEdgeOptions() {
    return new EdgeOptions().addArguments("--no-sandbox");
}
Ticket Compliance
🎫 No ticket provided
  • Create ticket/issue
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

🔴
Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status:
Hardcoded credentials: The tests introduce hardcoded credentials and embed them into a URL, which risks
credential leakage via logs, stack traces, proxies, or other URL capture mechanisms.

Referred Code
public void remoteWebDriverWithClientConfig() throws Exception {
    ClientConfig clientConfig = ClientConfig.defaultConfig()
            .withRetries()
            .sslContext(createSSLContextWithCA(Path.of("src/test/resources/tls.crt").toAbsolutePath().toString()))
            .connectionTimeout(Duration.ofSeconds(300))
            .readTimeout(Duration.ofSeconds(3600))
            .authenticateAs(new UsernameAndPassword("admin", "myStrongPassword"))
            .version(HTTP_1_1.toString());
    ChromeOptions options = getDefaultChromeOptions();
    options.setEnableDownloads(true);
    driver = RemoteWebDriver.builder()
            .oneOf(options)
            .address(gridUrl)
            .config(clientConfig)
            .build();
}

@Test
public void remoteWebDriverIgnoreSSL() throws Exception {
    ClientConfig clientConfig = ClientConfig.defaultConfig()
            .withRetries()


 ... (clipped 34 lines)

Learn more about managing compliance generic rules or creating your own custom rules

  • Update
Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

@qodo-code-review
Copy link
Contributor

qodo-code-review bot commented Jan 21, 2026

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
Possible issue
Add AfterEach to quit driver

Add a JUnit @AfterEach method to HttpClientTest to close the RemoteWebDriver
session after each test. This prevents resource leaks by ensuring driver.quit()
is called.

examples/java/src/test/java/dev/selenium/drivers/HttpClientTest.java [47-50]

-driver = new RemoteWebDriver.Builder()
-    .address(gridUrl)
-    .config(clientConfig)
-    .build();
+@AfterEach
+public void closeBrowser() {
+  if (driver != null) {
+    driver.quit();
+  }
+}

[To ensure code accuracy, apply this suggestion manually]

Suggestion importance[1-10]: 8

__

Why: The suggestion correctly points out a resource leak risk, as HttpClientTest creates RemoteWebDriver instances without ensuring they are closed. Adding an @AfterEach method to quit the driver is a critical fix for test stability and resource management.

Medium
Extend BaseTest for cleanup

Modify EdgeTest to extend BaseTest. This will allow it to inherit the shared
@AfterEach teardown logic, ensuring the WebDriver session is automatically
closed after each test.

examples/java/src/test/java/dev/selenium/browsers/EdgeTest.java [21]

-public class EdgeTest {
+public class EdgeTest extends BaseTest {

[To ensure code accuracy, apply this suggestion manually]

Suggestion importance[1-10]: 8

__

Why: The suggestion correctly identifies that EdgeTest is missing teardown logic, which can lead to resource leaks. Extending BaseTest is the standard pattern in this codebase for ensuring proper driver cleanup and is a critical improvement.

Medium
Avoid double-quitting the WebDriver instance

Remove the shadowed driver field and redundant cleanup logic in FirefoxTest.
Instead, utilize the driver and @AfterEach cleanup method from the BaseTest
superclass for consistency.

examples/java/src/test/java/dev/selenium/browsers/FirefoxTest.java [21-31]

 public class FirefoxTest extends BaseTest {
-  private FirefoxDriver driver;
 
   @AfterEach
   public void clearProperties() {
     System.clearProperty(GeckoDriverService.GECKO_DRIVER_LOG_PROPERTY);
     System.clearProperty(GeckoDriverService.GECKO_DRIVER_LOG_LEVEL_PROPERTY);
-    if (driver != null) {
-      driver.quit();
-    }
   }
  • Apply / Chat
Suggestion importance[1-10]: 7

__

Why: The suggestion correctly identifies that FirefoxTest shadows the driver field from BaseTest and has its own cleanup logic, which is inconsistent with the PR's goal of centralizing driver management. Removing the local driver and its cleanup would improve consistency and rely on the base class implementation.

Medium
  • Update

@asolntsev
Copy link
Contributor Author

I see multiple flaky tests here...

Will tackle them in a following PR.

@asolntsev asolntsev requested review from cgoldberg and diemol January 22, 2026 18:32
Co-authored-by: Swastik Baranwal <swstkbaranwal@gmail.com>
@asolntsev
Copy link
Contributor Author

@diemol Just in case, I cannot merge this PR by myself... :(

@diemol diemol merged commit e4d6a20 into SeleniumHQ:trunk Jan 23, 2026
10 checks passed
@asolntsev asolntsev deleted the refactor/java-examples branch January 23, 2026 11:46
@asolntsev asolntsev self-assigned this Jan 23, 2026
@asolntsev
Copy link
Contributor Author

@diemol The example on site is still outdated: https://www.selenium.dev/documentation/webdriver/getting_started/using_selenium/#tabs-8-content

Is there some other GA build that should publish Java code to the site?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants