
- Selenium - Home
- Selenium - Overview
- Selenium - Components
- Selenium - Automation Testing
- Selenium - Environment Setup
- Selenium - Remote Control
- Selenium - IDE Introduction
- Selenium - Features
- Selenium - Limitations
- Selenium - Installation
- Selenium - Creating Tests
- Selenium - Creating Script
- Selenium - Control Flow
- Selenium - Store Variables
- Selenium - Alerts & Popups
- Selenium - Selenese Commands
- Selenium - Actions Commands
- Selenium - Accessors Commands
- Selenium - Assertions Commands
- Selenium - Assert/Verify Methods
- Selenium - Locating Strategies
- Selenium - Script Debugging
- Selenium - Verification Points
- Selenium - Pattern Matching
- Selenium - JSON Data File
- Selenium - Browser Execution
- Selenium - User Extensions
- Selenium - Code Export
- Selenium - Emitting Code
- Selenium - JavaScript Functions
- Selenium - Plugins
- Selenium WebDriver Tutorial
- Selenium - Introduction
- Selenium WebDriver vs RC
- Selenium - Installation
- Selenium - First Test Script
- Selenium - Driver Sessions
- Selenium - Browser Options
- Selenium - Chrome Options
- Selenium - Edge Options
- Selenium - Firefox Options
- Selenium - Safari Options
- Selenium - Double Click
- Selenium - Right Click
- HTML Report in Python
- Handling Edit Boxes
- Selenium - Single Elements
- Selenium - Multiple Elements
- Selenium Web Elements
- Selenium - File Upload
- Selenium - Locator Strategies
- Selenium - Relative Locators
- Selenium - Finders
- Selenium - Find All Links
- Selenium - User Interactions
- Selenium - WebElement Commands
- Selenium - Browser Interactions
- Selenium - Browser Commands
- Selenium - Browser Navigation
- Selenium - Alerts & Popups
- Selenium - Handling Forms
- Selenium - Windows and Tabs
- Selenium - Handling Links
- Selenium - Input Boxes
- Selenium - Radio Button
- Selenium - Checkboxes
- Selenium - Dropdown Box
- Selenium - Handling IFrames
- Selenium - Handling Cookies
- Selenium - Date Time Picker
- Selenium - Dynamic Web Tables
- Selenium - Actions Class
- Selenium - Action Class
- Selenium - Keyboard Events
- Selenium - Key Up/Down
- Selenium - Copy and Paste
- Selenium - Handle Special Keys
- Selenium - Mouse Events
- Selenium - Drag and Drop
- Selenium - Pen Events
- Selenium - Scroll Operations
- Selenium - Waiting Strategies
- Selenium - Explicit/Implicit Wait
- Selenium - Support Features
- Selenium - Multi Select
- Selenium - Wait Support
- Selenium - Select Support
- Selenium - Color Support
- Selenium - ThreadGuard
- Selenium - Errors & Logging
- Selenium - Exception Handling
- Selenium - Miscellaneous
- Selenium - Handling Ajax Calls
- Selenium - JSON Data File
- Selenium - CSV Data File
- Selenium - Excel Data File
- Selenium - Cross Browser Testing
- Selenium - Multi Browser Testing
- Selenium - Multi Windows Testing
- Selenium - JavaScript Executor
- Selenium - Headless Execution
- Selenium - Capture Screenshots
- Selenium - Capture Videos
- Selenium - Page Object Model
- Selenium - Page Factory
- Selenium - Record & Playback
- Selenium - Frameworks
- Selenium - Browsing Context
- Selenium - DevTools
- Selenium Grid Tutorial
- Selenium - Overview
- Selenium - Architecture
- Selenium - Components
- Selenium - Configuration
- Selenium - Create Test Script
- Selenium - Test Execution
- Selenium - Endpoints
- Selenium - Customizing a Node
- Selenium Reporting Tools
- Selenium - Reporting Tools
- Selenium - TestNG
- Selenium - JUnit
- Selenium - Allure
- Selenium & other Technologies
- Selenium - Java Tutorial
- Selenium - Python Tutorial
- Selenium - C# Tutorial
- Selenium - Javascript Tutorial
- Selenium - Kotlin Tutorial
- Selenium - Ruby Tutorial
- Selenium - Maven & Jenkins
- Selenium - Database Testing
- Selenium - LogExpert Logging
- Selenium - Log4j Logging
- Selenium - Robot Framework
- Selenium - AutoIT
- Selenium - Flash Testing
- Selenium - Apache Ant
- Selenium - Github Tutorial
- Selenium - SoapUI
- Selenium - Cucumber
- Selenium - IntelliJ
- Selenium - XPath
- Selenium Miscellaneous Concepts
- Selenium - IE Driver
- Selenium - Automation Frameworks
- Selenium - Keyword Driven Framework
- Selenium - Data Driven Framework
- Selenium - Hybrid Driven Framework
- Selenium - SSL Certificate Error
- Selenium - Alternatives
Selenium Grid - Customizing a Node
The latest version of Selenium Grid 4, is developed without leveraging the code base of the older versions of the Selenium Grid. This latest version of Selenium Grid 4 version has some advanced features like the customizing a Node.
The latest version of Selenium Grid allows test execution to be triggered in three different Selenium Grid modes. They are known as the Standalone, Hub and Nodes, and the Distributed.
Node Customization in Selenium Grid
While using the Selenium Grid to perform parallel testing or cross browser testing across different browsers and its platforms, devices, we may require to customize the Node as per requirements.
We may need to add some prerequisite steps prior to starting of the execution sessions or any tidying up activities post the sessions completed. To perform a Node customization the below steps are to be performed −
Design a class which will extend the −
org.openqa.selenium.grid.node.Node.
Append a static method(a factory method) to the newly designed class which should have the signature: public static Node created(Config config). Here, the Node has the same type as org.openqa.selenium.grid.node.Node and Config has the same type as −
org.openqa.selenium.grid.config.Config.
Inside the factory method, the implementation logic of the new class should be added.
To incorporate the newly developed implementation inside the hub, begin the node and send in the completely qualified class name of the previous to the argument: node-implementation.
Node Customization Using the Uber Jar
The steps to implement node customization using the uber jar is listed below −
Install Java(version above 8) in the system and check if it is present with the command: java -version. The java version installed will be visible if installation has been completed successfully.
Install maven in the system and check if it is present with the command: mvn -version. The maven version installed will be visible if installation has been completed successfully.
Install any IDE like Eclipse, IntelliJ, and so on.
-
Add the Selenium Grid dependencies to the pom.xml from the link −
https://mvnrepository.com/artifact/.
-
Add the Apache Maven Shade Plugin to the pom.xml from the link −
https://mvnrepository.com/artifact/.
Append the customized node to the current project.
Build the uber jar to kick off the Node with the help of the command: java -jar.
Begin the Node using the below command −
java -jar custom_node-server.jar node \ --node-implementation org.seleniumhq.samples.DecoratedLoggingNode
Node Customization Using a Normal Jar
The steps to implement node customization using a normal jar is listed below −
Install Java(version above 8) in the system and check if it is present with the command: java -version. The java version installed will be visible if installation has been completed successfully.
Install maven in the system and check if it is present with the command: mvn -version. The maven version installed will be visible if installation has been completed successfully.
Install any IDE like Eclipse, IntelliJ, and so on.
Add the Selenium Grid dependencies to the pom.xml from the link − https://mvnrepository.com/artifact/.
Add the Apache Maven Shade Plugin to the pom.xml from the link − https://maven.apache.org/plugins/.
Append the customized node to the current project.
Build the uber jar to kick off the Node with the help of the command: java -jar.
Begin the Node using the below command −
java -jar selenium-server-4.6.0.jar \ --ext custom_node-1.0-SNAPSHOT.jar node \ --node-implementation org.seleniumhq.samples.DecoratedLoggingNode
Code Implementation in DecoratedLoggingNode.java
package org.seleniumhq.samples; import java.io.IOException; import java.net.URI; import java.util.UUID; import java.util.function.Supplier; import org.openqa.selenium.Capabilities; import org.openqa.selenium.NoSuchSessionException; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.grid.config.Config; import org.openqa.selenium.grid.data.CreateSessionRequest; import org.openqa.selenium.grid.data.CreateSessionResponse; import org.openqa.selenium.grid.data.NodeId; import org.openqa.selenium.grid.data.NodeStatus; import org.openqa.selenium.grid.data.Session; import org.openqa.selenium.grid.log.LoggingOptions; import org.openqa.selenium.grid.node.HealthCheck; import org.openqa.selenium.grid.node.Node; import org.openqa.selenium.grid.node.local.LocalNodeFactory; import org.openqa.selenium.grid.security.Secret; import org.openqa.selenium.grid.security.SecretOptions; import org.openqa.selenium.grid.server.BaseServerOptions; import org.openqa.selenium.internal.Either; import org.openqa.selenium.io.TemporaryFilesystem; import org.openqa.selenium.remote.SessionId; import org.openqa.selenium.remote.http.HttpRequest; import org.openqa.selenium.remote.http.HttpResponse; import org.openqa.selenium.remote.tracing.Tracer; public class DecoratedLoggingNode extends Node { private Node node; protected DecoratedLoggingNode(Tracer tracer, NodeId nodeId, URI uri, Secret registrationSecret) { super(tracer, nodeId, uri, registrationSecret); } public static Node create(Config config) { LoggingOptions loggingOptions = new LoggingOptions(config); BaseServerOptions serverOptions = new BaseServerOptions(config); URI uri = serverOptions.getExternalUri(); SecretOptions secretOptions = new SecretOptions(config); // Refer to the foot notes for additional context on this line. Node node = LocalNodeFactory.create(config); DecoratedLoggingNode wrapper = new DecoratedLoggingNode(loggingOptions.getTracer(), node.getId(), uri, secretOptions.getRegistrationSecret()); wrapper.node = node; return wrapper; } @Override public Either<WebDriverException, CreateSessionResponse> newSession( CreateSessionRequest sessionRequest) { return perform(() -> node.newSession(sessionRequest), "newSession"); } @Override public HttpResponse executeWebDriverCommand(HttpRequest req) { return perform(() -> node.executeWebDriverCommand(req), "executeWebDriverCommand"); } @Override public Session getSession(SessionId id) throws NoSuchSessionException { return perform(() -> node.getSession(id), "getSession"); } @Override public HttpResponse uploadFile(HttpRequest req, SessionId id) { return perform(() -> node.uploadFile(req, id), "uploadFile"); } @Override public HttpResponse downloadFile(HttpRequest req, SessionId id) { return perform(() -> node.downloadFile(req, id), "downloadFile"); } @Override public TemporaryFilesystem getDownloadsFilesystem(UUID uuid) { return perform(() -> { try { return node.getDownloadsFilesystem(uuid); } catch (IOException e) { throw new RuntimeException(e); } }, "downloadsFilesystem"); } @Override public TemporaryFilesystem getUploadsFilesystem(SessionId id) throws IOException { return perform(() -> { try { return node.getUploadsFilesystem(id); } catch (IOException e) { throw new RuntimeException(e); } }, "uploadsFilesystem"); } @Override public void stop(SessionId id) throws NoSuchSessionException { perform(() -> node.stop(id), "stop"); } @Override public boolean isSessionOwner(SessionId id) { return perform(() -> node.isSessionOwner(id), "isSessionOwner"); } @Override public boolean isSupporting(Capabilities capabilities) { return perform(() -> node.isSupporting(capabilities), "isSupporting"); } @Override public NodeStatus getStatus() { return perform(() -> node.getStatus(), "getStatus"); } @Override public HealthCheck getHealthCheck() { return perform(() -> node.getHealthCheck(), "getHealthCheck"); } @Override public void drain() { perform(() -> node.drain(), "drain"); } @Override public boolean isReady() { return perform(() -> node.isReady(), "isReady"); } private void perform(Runnable function, String operation) { try { System.err.printf("[COMMENTATOR] Before %s()%n", operation); function.run(); } finally { System.err.printf("[COMMENTATOR] After %s()%n", operation); } } private <T> T perform(Supplier<T> function, String operation) { try { System.err.printf("[COMMENTATOR] Before %s()%n", operation); return function.get(); } finally { System.err.printf("[COMMENTATOR] After %s()%n", operation); } } }
Source for DecoratedLoggingNode.java − https://www.selenium.dev/documentation/.
In the above implementation, the below code −
Node node = LocalNodeFactory.create(config) is used to generate the LocalNode specifically. There are two types of user facing implementations of the org.openqa.selenium.grid.node.Node. These are excellent beginning areas to create a custom Node and to gather information on a Node.
org.openqa.selenium.grid.node.local.LocalNode − This is used to point to a Node which is running for a long time and is the default logic that is fetched while a Node is started. It can be generated by calling the LocalNodeFactory.create(config). Here, the LocalNodeFactory is a part of the org.openqa.selenium.grid.node.local and Config is a part of the org.openqa.selenium.grid.config.
org.openqa.selenium.grid.node.k8s.OneShotNode − This is an important reference logic where the Node shuts itself down properly post one test session. This class is unavailable to any pre-existing maven artifact. It can be generated by calling the OneShotNode.create(config). Here, the OneShotNode is a part of the org.openqa.selenium.grid.node.k8s and Config is a part of the org.openqa.selenium.grid.config.
This concludes our comprehensive take on the tutorial on Selenium Grid - Customizing a Node. Weve started with describing how to perform a Node customization in Selenium Grid, Node Customization using the uber jar, and Node Customization using a normal jar in Selenium Grid.
This equips you with in-depth knowledge of the Selenium Grid Customizing a Node. It is wise to keep practicing what youve learned and exploring others relevant to Selenium to deepen your understanding and expand your horizons.