Selenium 4 features significant enhancements over Selenium 3, including a revamped Selenium Grid for distributed testing, native support for HTML5, and integration of the W3C WebDriver protocol for improved compatibility. Additionally, it offers enhanced debugging and error-handling capabilities, streamlining the testing process for better efficiency and reliability.
Benefits of Selenium Automation: Exploring Selenium 4 New Features
Streamline Testing Processes: Selenium automation allows organizations to streamline and enhance their testing processes by automating repetitive tasks associated with web application testing.
Interact with Web Elements: Automation scripts, facilitated by Selenium’s WebDriver, interact with web elements, imitating user actions to test functionality.
Accelerate Testing: Selenium automation accelerates testing by eliminating manual intervention and executing tests efficiently.
Ensure Consistency and Reliability: By automating tests, Selenium ensures consistent and reliable results across diverse browser environments, reducing the risk of human error.
Faster Releases: Selenium automation acts as a catalyst for achieving faster releases by expediting the testing phase.
Improve Test Coverage: With automation, organizations can improve test coverage by running tests more frequently and comprehensively.
Maintain Application Integrity: Selenium automation helps in maintaining the integrity of web applications by identifying and addressing issues promptly.
The Architecture of Selenium 3
The Architecture of Selenium 4
Selenium 4 New Features:W3C WebDriver Standardization
Selenium 4 fully supports the W3C WebDriver standard, improving compatibility across different browsers and reducing inconsistencies.
Standardized Communication:The adoption of the W3C WebDriver protocol ensures consistent behavior across different browsers, reducing compatibility issues.
Improved Grid Architecture: Enhanced scalability and easier management with support for distributed mode, Docker, and Kubernetes.
User-Friendly Selenium IDE: Modernized interface and parallel test execution simplify test creation and management.
Enhanced Browser Driver Management: Unified driver interface and automatic updates reduce manual configuration and ensure compatibility.
Advanced Browser Interactions: Integration with DevTools Protocols for Chrome and Firefox enables comprehensive network and performance monitoring.
Simplified Capabilities Configuration: Using Options classes instead of DesiredCapabilities improves the readability and maintainability of test scripts.
Improved Actions API: Enhancements provide more reliable and consistent complex user interactions across different browsers.
Enhanced Performance: Overall performance improvements result in faster and more efficient test execution.
Better Documentation: Comprehensive and improved documentation reduces the learning curve and enhances productivity.
Backward Compatibility: Designed to be backward compatible, allowing seamless upgrades without significant changes to existing test scripts.
Here, I’ll outline the precise changes introduced in Selenium 4 when compared to its earlier versions:
1. W3C WebDriver Protocol:
Selenium 4 further aligns with the W3C WebDriver standard, ensuring better compatibility across different browsers.
Full support for the W3C WebDriver protocol was a significant improvement to enhance consistency and stability across browser implementations.
2. New Grid :
Selenium Grid has been updated in Selenium 4 with a new version known as the “Grid 4”.
The new grid is more scalable and provides better support for Docker and Kubernetes.
Let’s briefly understand Selenium Grid, which consists of two major components:
Node: Used to execute tests on individual computer systems, there can be multiple nodes in a grid.
Hub: The central point from which it controls all the machines present in the network. It contains only one hub, which helps in allocating test execution to different nodes.
In Selenium 4, the Grid is highly flexible. It allows testing cases against multiple browsers, browsers of different versions, and also on different operating systems.
Even now, there is no need for a setup to start the hub and nodes individually. Once the user starts the server, the Grid automatically functions as both nodes and hub.
3. Relative Locators:
Selenium 4 introduced a new set of locators called “Relative Locators” or “Relative By”.
Relative Locators provide a more natural way of interacting with elements concerning their surrounding elements, making it easier to write maintainable tests.
There are five locators added in Selenium 4:
below(): Web element located below the specified element.
toLeftOf(): Target web element present to the left of the specified element.
toRightOf(): Target web element presented to the right of the specified element.
above(): Web element located above the specified element.
near(): Target web element away (approximately 50 pixels) from the specified element.
Note: All the above relative locator methods support the withTagName method.
The below example demonstrates the toLeftOf() and below() locators:
WebElement book = driver.findElement(RelativeLocators.withTagName("li").toLeftOf(By.id("pid1")).below(By.id("pid2")));
String id1 = book.getAttribute("id1");
The below example illustrates the toRightOf() and above() locators:
Selenium IDE received significant updates with Selenium 4 new features, making it more powerful and versatile for recording and playing back test scenarios.
The Selenium IDE has become a browser extension available for Chrome and Firefox.
The features include:
Improved Browser Support:
The new version enhances browser support, allowing any browser vendor to seamlessly integrate with the latest Selenium IDE.
CLI Runner Based on NodeJS:
The Command Line Interface (CLI) Runner is now built on NodeJS instead of the HTML-based runner.
It supports parallel execution, providing a more efficient way to execute tests concurrently.
The CLI Runner generates a comprehensive report, detailing the total number of test cases passed and failed, along with the execution time taken.
These improvements in Selenium IDE aim to enhance compatibility with various browsers and provide a more versatile and efficient test execution environment through the CLI Runner based on NodeJS.
5. New Window Handling API:
Selenium 4 introduced a new Window interface, providing a more consistent and convenient way to handle browser windows and tabs.
if the user wants to access two applications in the same browser, follow the below code
driver.get(“https://www.google.com/”);
driver.switchTo().newWindow(WindowType.WINDOW);
driver.navigate().to(“https://www.bing.com/”);
Set<String> windowHandles = driver.getWindowHandles();
for (String handle : windowHandles) {
driver.switchTo().window(handle);
// Perform actions on each window
}
6. Improved DevTools API:
Selenium 4 provides enhanced support for interacting with the browser DevTools using the DevTools API.
This allows testers to perform advanced browser interactions and access additional information about the browser.
In the new version of Selenium 4, they have made some internal changes in the API. Earlier in Selenium 3, the Chrome driver directly extended the Remote Web Driver class. However, in Selenium 4, the Chrome driver class now extends to the Chromium Driver class.The Chromium Driver class has some predefined methods to access the dev tool, highlighting the new features of Selenium 4.
Note: Chromium Driver extends the Remote Web driver class.
By using the API, we can perform the following operations:
In Selenium 4, a notable enhancement is the provision to capture a screenshot of a specific web element, which was unavailable in earlier versions. This feature lets users focus on capturing images of individual elements on a webpage, providing more targeted and precise visual information during testing or debugging processes. The capability to take screenshots of specific web elements enhances the flexibility and granularity of testing scenarios, making Selenium 4 a valuable upgrade for web automation tasks. Among the various Selenium 4 features, this improvement stands out for its practical application in detailed web testing.
In Selenium 4, the parameters received in Waits and Timeout have changed from expecting (long time, TimeUnit unit) to expect (Duration duration) which you see a deprecation message for all tests.
WebDriverWait is also now expecting a ‘Duration’ instead of a long for timeout in seconds and milliseconds.
The method is now deprecated in selenium public WebDriverWait(@NotNull org.openqa.selenium.WebDriver driver, long timeoutInSeconds)
Before Selenium 4 –
//Old syntax
WebDriverWait wait = new WebDriverWait(driver,10);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector(".classlocator")));
After Selenium 4 –
//Selenium 4 syntax
WebDriverWait wait = new WebDriverWait(driver,Duration.ofSeconds(10));
wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector(".classlocator")));
FluentWait –
Before Selenium 4 –
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(30, TimeUnit.SECONDS)
.pollingEvery(5, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class);
After Selenium 4 –
Wait<WebDriver> fluentWait = new FluentWait<WebDriver>(driver)
.withTimeout(Duration.ofSeconds(30))
.pollingEvery(Duration.ofSeconds(5))
.ignoring(NoSuchElementException.class);
9. Bi-Directional Communication:
Selenium 4 introduced better bi-directional communication between Selenium and browser drivers.
This allows for more efficient communication, resulting in improved performance and stability.
10. Enhanced Documentation:
Selenium 4 comes with improved and updated documentation, making it easier for users to find information and resources related to Selenium.
11. Support for Chrome DevTools Protocol (CDP):
Selenium 4 allows users to interact with Chrome DevTools using the Chrome DevTools Protocol directly.
Conclusion:
Selenium 4 marks a substantial leap forward, addressing limitations present in Selenium 3 and introducing new features to meet the evolving needs of web automation. The Relative Locators, enhanced window handling, improved DevTools API, and Grid 4 support make Selenium 4 a powerful and versatile tool for testers and developers in the realm of web testing and automation.
Click here for more blogs on software testing and test automation.
Harish is an SDET with expertise in API, web, and mobile testing. He has worked on multiple Web and mobile automation tools including Cypress with JavaScript, Appium, and Selenium with Python and Java. He is very keen to learn new Technologies and Tools for test automation. His latest stint was in TestProject.io. He loves to read books when he has spare time.
Web tables, also known as HTML tables, are a widely used format for displaying data on web pages. They allow for a structured representation of information in rows and columns, making it easy to read and manipulate data. Selenium WebDriver, a powerful tool for web browser automation, provides the functionality to interact with these tables programmatically. This capability is beneficial for tasks like web scraping, automated testing, and data validation. In this blog, we will see how to extract data from Web tables in Java-Selenium.
Identify web table from your webpage:
To effectively identify and interact with web tables using Selenium, it’s crucial to understand the HTML structure of tables and the specific tags used. Here’s an overview of the key table-related HTML tags
A typical HTML table consists of several tags that define its structure:
<table>: The main container for the table.
<thead>: Defines the table header, which contains header rows (<tr>).
<tbody>: Contains the table body, which includes the data rows.
<tr>:Defines a table row.
<th>: Defines a header cell in a table row.
<td>: Defines a standard data cell in a table row.
As a demo website, here you will get a sample WebTable with fields like first name, last name, email, etc. Here we have applied a filter for email to minimize the size of the table.
We will be starting by launching the browser and navigating to the webpage. We have applied a filter for the email “PolGermain@whatever.com”, you can change it as per your requirement.
Once we get the filtered data from the table, now we need to locate the table and get the number of rows. The table will have multiple rows so, we need to use a list to store all the rows.
As we have stored all the rows in the list, now we need to iterate through each rows to fetch the columns and store the column data in another list.
Example :
Abc
1
Xyz
2
table has 2 rows and 2 columns
When we are iterating through the 1st row we will get data as Abc and 1 and store it in the list ’as rowdata[Abc, 1] similarly data from the 2nd row will be stored as rowdata[Xyz, 2].When we are iterating through the 2nd row the data from the 1st row will be overwritten. That’s why we will need one more list ‘webRows ’ to store all the rows. In the below code snippet, here we are iterating through all the columns from each row one by one and finally storing all the rows in the list WebRows.
We have successfully extracted the table data now you can use this data as per your requirement
To do this we need to iterate through the list ‘webRows’ where we have our table data stored. We will be accessing all the columns by their index. In this case, you should know the column index you want to access. The column index always starts from 0.
for (int s = 0; s < webRows.size(); s++) {
List<String> row = webRows.get(s);
System.out.println(row.get(1));
System.out.println(row);
}
Below is the complete code snippet for the above-mentioned steps. You need to update related Xpaths in case you are not able to access the rows and columns with the given Xpaths.
Instead of accessing data by the index, you can access it using the column index also, and to do that you need to use the HashMaps instead of lists. HashMap will help to store column headers as keys and column data as values
Example:
Name
Id
Abc
1
Xyz
2
Table has 3 rows and 2 columns
Here Name and ID will be your keys and Abc, 1 and Xyz, 2 will be the values.
How to store and access table data using HashMap?
The code snippet below shows how to use HashMap to store data in key-value format.
package Selenium;
import io.github.bonigarcia.wdm.WebDriverManager;
import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
import java.util.ArrayList;
import java.util.List;
public class Webtable_Blog {
public static void main(String[] args) throws InterruptedException {
WebDriverManager.chromedriver().setup();
WebDriver driver = new ChromeDriver();
driver.get("https://www.globalsqa.com/angularJs-protractor/WebTable/");
driver.manage().window().maximize();
WebElement global_search = driver.findElement(By.xpath("//input[@type='search' and @placeholder='global search']"));
global_search.sendKeys("PolGermain@whatever.com");
// global_search.sendKeys("Pol");
global_search.sendKeys(Keys.ENTER);
Thread.sleep(5000);
List<WebElement> rows = driver.findElements(By.xpath("//table[@class='table table-striped']/tbody/tr"));
System.out.println("size-"+rows.size());
List<Map<String, String>> webRows = new ArrayList<>();
for (int i = 0; i < rows.size(); i++) {
List<WebElement> keys = driver.findElements(By.xpath("//table[@class='table table-striped']/thead/tr[1]/th"));
List<WebElement> values = driver.findElements(By.xpath("//table[@class='table table-striped']/tbody/tr["+(i+1)+"]/td"));
Map<String, String> webColumn = new HashMap<>();
try {
for (int j = 0; i < keys.size(); j++) {
webColumn.put(keys.get(j).getText(), values.get(j).getText());
}
} catch (Exception e) {
}
webRows.add(webColumn);
}
for (int s = 0; s < webRows.size(); s++) {
System.out.println(webRows.get(s).get("lastName"));
System.out.println(webRows.get(s));
}
}
}
In this blog, we’ve delved into the powerful capabilities of Selenium WebDriver for handling web tables in Java. WebTables are a crucial part of web applications, often used to display large amounts of data in an organized manner. In Java Selenium, handling these WebTables efficiently is a key skill for any test automation engineer. Throughout this blog, we’ve explored various techniques to interact with WebTables, including locating tables, accessing rows and cells, iterating through table data, and performing actions like sorting and filtering.
Click here for more blogs on software testing and test automation.
Priyanka is an SDET with 2.5+ years of hands-on experience in Manual, Automation, and API testing. The technologies she has worked on include Selenium, Playwright, Cucumber, Appium, Postman, SQL, GitHub, and Java. Also, she is interested in Blog writing and learning new technologies.
In this Blog, I’ll walk you through the process of fetching an email link and OTP from Email using Python. Learn how to fetch links & OTP from email efficiently with simple steps. Email and OTP (One-Time Password) verification commonly ensure security and verify user identity in various scenarios.
Some typical scenarios include:
User Registration
Password Reset
Two-factor authentication (2FA)
Transaction Verification
Subscription Confirmation
We’ll leverage the imap_tools library to interact with Gmail’s IMAP server. We’ll securely manage our credentials using the dotenv library. This method is efficient and ensures that your email login details remain confidential.
Store Credentials Securely to Fetch OTP from Email:
A .env file is typically used to store environment variables. This file contains key-value pairs of configuration settings and sensitive information that your application needs to run but which you do not want to hard-code into your scripts for security and flexibility reasons.
Create a .env file in your project directory to store your Gmail credentials.
EMAIL_USER=your-email@gmail.com
EMAIL_PASS=your-password
How to Create and Use an App Password for Gmail
To securely fetch emails using your Gmail account in a Python script, you should use an App Password.
This is especially important if you have two-factor authentication (2FA) enabled on your account.
Here’s a step-by-step guide on how to generate an App Password in Gmail:
Go to your Google Account settings.
Select “Security” from the left-hand menu.
Enable Two-Factor Authentication:
Go to your Google Account Security Page.
Under the “Signing in to Google” section, ensure that 2-Step Verification is turned on. If it’s not enabled, click on “2-Step Verification” and follow the instructions to set it up.
Generate an App Password:
Once 2-step Verification is enabled, return to the Google Account Security Page.
Under the “Signing in to Google” section, you will now see an option for “App passwords.” Click on it.
You might be prompted to re-enter your Google account password.
In the “Select app” dropdown, choose “Mail” or “Other (Custom name)” and provide a name (e.g., “Python IMAP”).
In the “Select device” dropdown, choose the device you’re generating the password for, or select “Other (Custom name)” and enter a name (e.g., “My Computer”).
Click on “Generate.”
Google will provide you with a 16-character password. Note this password down securely, as you’ll need it for your Python script.
Load Environment Variables:
In your Python script, use the dotenv library to load these credentials securely. Here’s how you can do it:
from dotenv import load_dotenv
from imap_tools import MailBox, AND
import os
# Load .env file
load_dotenv()
# Read variables
email_user = os.getenv('EMAIL_USER')
email_pass = os.getenv('EMAIL_PASS')
Loading Environment Variables:
The dotenv library is used to load the email username and password from the .env file. This approach keeps your credentials secure and out of your source code.
Connect to Gmail and Fetch Emails:
We will create a function to connect to Gmail’s IMAP server and fetch the latest unread email. The function will look like this:
def check_latest_email():
# Connect to Gmail's IMAP server
with MailBox('imap.gmail.com').login(email_user, email_pass, 'INBOX') as mailbox:
# Fetch the latest unread email
emails = list(mailbox.fetch(AND(seen=False), limit=1, reverse=True))
if len(emails) == 0:
return None, None, None # No Emails Found
return emails[0]
if __name__ == "__main__":
email = check_latest_email()
if email:
print("Email subject: ", email.subject)
print("Email text: ", email.text)
print("Email from: ", email.from_)
else:
print("No new emails found.")
Connecting to Gmail’s IMAP Server:
Using the imap_tools library, we connect to Gmail’s IMAP server.
The MailBox class handles the connection.
The login method authenticates using your email and password.
Fetching the Latest Unread Email:
The fetch method retrieves emails based on specified criteria.
AND(seen=False) ensures we only get unread emails.
limit=1 fetches the latest one.
reverse=True sorts the emails in descending order.
Handling Email Data:
The function check_latest_email returns the most recent unread email’s subject, text, and sender.
If no new emails are found, it returns None.
By following these steps, you can efficiently fetch the latest unread email from your Gmail inbox using Python.
This method is not only secure but also straightforward, making it easy to integrate into your projects.
Fetching the link from email:
def extract_link(email_text):
# Regex pattern to match URLs
url_pattern = re.compile(r'https?://[^\s]+')
match = url_pattern.search(email_text)
if match:
return match.group()
return None
#Example to fetch link from email content:
link = extract_link(email.text)
if link:
print("Extracted Link: ", link)
else:
print("No link found in the email content.")
Fetching OTP from email:
Create a function to extract the OTP from the email content using a regular expression. This assumes the OTP is a 6-digit number, which is common for many services:
def extract_otp(email_text):
# Regex pattern to match a 6-digit number
otp_pattern = re.compile(r'\b\d{6}\b')
match = otp_pattern.search(email_text)
if match:
return match.group()
return None
#Example to extract otp from email
otp = extract_otp(email.text)
if otp:
print("Extracted OTP: ", otp)
else:
print("No OTP found in the email content.")
Refer to the following GitHub repository for instructions on how to fetch links and OTPs from Gmail.
Fetching links and OTPs from email content programmatically is essential for enhancing security, improving user experience, and increasing operational efficiency. Automation ensures timely and accurate processing, reducing the risk of errors and phishing attacks while providing a seamless user experience. This approach allows businesses to scale their operations, maintain compliance, and focus on strategic activities.
Click here for more blogs on software testing and test automation.
Harish is an SDET with expertise in API, web, and mobile testing. He has worked on multiple Web and mobile automation tools including Cypress with JavaScript, Appium, and Selenium with Python and Java. He is very keen to learn new Technologies and Tools for test automation. His latest stint was in TestProject.io. He loves to read books when he has spare time.
Over the years, the landscape of software testing has gradually developed from a predominantly manual testing phase to an increasing accentuation on automated/automation testing. In your career path as a test engineer, you will inevitably bump into automation testing. In the current landscape of the software industry, clients seek frequent and repetitive deployments. If you are in a role of Quality Assurance, you are likely to encounter and test systems needing frequent requirement changes or the rapid introduction of new and progressive requirements. Such a dynamic landscape calls for a constant adaptation to frequent code changes within stiff deadlines. A challenge that we can effectively address by adopting automation testing methodologies.
Why to Automate Chrome Extension:
We often use Chrome extensions in our daily activities, which is crucial for enhancing productivity. The repetitive nature of certain tasks associated with these extensions can become monotonous over time. This blog aims to guide you through the process of automating Chrome extensions and executing click actions using Selenium, a widely acclaimed open-source test automation framework introduced in 2004. If you find yourself needing to use a particular extension regularly, the conventional method involves manually adding the extension to Chrome and performing the same task repeatedly. This manual repetition not only increases effort but also consumes valuable time. Therefore, to streamline this process and save both manual effort and time, we present a precise method to automate Chrome extensions and configure them seamlessly for efficient use.
How to Automate Chrome Extension:
In this article, we will learn the process of Automate Chrome extensions and performing click actions using the Selenium WebDriver and about the Robot Class in Selenium. We will examine them in the Chrome browser using Java. Here we go !!
Before moving on to the main topic of our discussion, let’s quickly review the techniques we will use to Automate Chrome extension and conduct action.
Implementation Steps to Automate Chrome Extension:
Add Calculator extension to the local Chrome browser.
Pack the extension and create a .crx file in File Explorer.
Create a Maven project using IntelliJ IDE.
Add dependencies in POM.xml file and Add .crx file in resources package.
Create Packages and files in the project.
5.1. Creating Features File.
5.2. Creating Steps file.
5.3. Creating Page Object Design Pattern.
5.4. Creating TestContext File.
5.5. Creating BaseStep File.
Conclusion
I intend to use simplified language while articulating the concepts. So, let’s dive into the core of our topic, which is how to Automate Chrome extensions and perform click actions using Selenium.
To do this, we will follow a few rules, which I have depicted below as steps.
Step 1: Add Calculator extension to the local Chrome browser.
In this article, we are going to use the Calculator extension to Automate Chrome extension and perform an action on an extension out of the DOM element.
To add calculator extension to local Chrome browser –
On the Extension page find the search box and search for the calculator extension.
Select calculator first and then download and click on add extension
After adding an extension, visit chrome://extensions/ URL from the address bar and then enable the Developer mode.
Also on this site, we can see our calculator extension which we just added.
On an extension, there could be an Extension ID. We have to note down this extension ID. In the next step, we will learn about generating a folder named extension ID in File Explorer.
In this article Extension ID is hcpbdjanfepobbkbnhmalalmfdmikmbe
Congratulations, we have completed our first step of Adding the Calculator extension to the local automate Chrome browser.
Now let’s begin with the next step.
Step 2: Pack the extension and create a .crx file in File Explorer
Before continuing with the second step we will learn what a .crx file extension is.
What is a .crx file extension?
A Chrome extension file has a .crx extension. It increases the functionality of the Google Chrome web browser by allowing third-party applications to supplement its basic functionality.
Now, we will learn how to pack the calculator extension and generate a .crx file extension.
After adding the calculator extension to the local Chrome browser, the file explorer will generate a folder with the name extension ID (hcpbdjanfepobbkbnhmalalmfdmikmbe).
Follow the provided path to locate the extension folder –
(to locate AppData we have to enable show hidden folders) C:➜Users➜{UserName}➜AppData➜Local➜Google➜Chrome➜User➜Data➜Default➜Extensions➜hcpbdjanfepobbkbnhmalalmfdmikmbe➜1.8.2_0
In the extension folder, we will find the folder named Extension ID, which we have noted down here hcpbdjanfepobbkbnhmalalmfdmikmbe is the Extension ID for calculator extension. Open that folder.
In the folder, we can see a version folder of the extension. Open that folder ➜1.8.2_0
Now we have to copy the path as mentioned in below image –
We will use this path to pack the extension in next steps.
Now, launch the Chrome browser and Visit chrome://extensions/ in the address bar
Here we can see the pack extension option.
➜ Click on Pack Extensionto automate chrome extension
After visiting the page we will be able to see the Pack Extension option as shown in the below image.
Here we have to type or paste the path that we had copied.
➜Add copied path to the Extension root directory
In this step, we have to paste a copied path to the Extension root directory to pack our Extension and then we have to click on the Pack Extension Button.
➜Copy the path of the .crx file
After clicking on the Pack Extension button a pop-up frame will appear. Here, we can see the path of the .crx file where it has been generated in File Explorer. Remember the path of the .crx file and click on the OK button.
➜ Navigate to the .crx file in file explorer
Now let’s navigate to the path of the .crx file as mentioned in the step above . Once we navigate to the path of the .crx file we can see the file has been generated. We have to use this .crx file in our maven project to display it in the selenium web driver and perform actions on it.
Congratulations!! We have successfully generated a .crx file.
Step 3: Create a Maven project using Intellij IDE.
Before creating a Maven project. Let’s understand what Maven is.
What is Maven?
Maven is a Java project management tool that the Apache Software Foundation developed. It is written in Java Language to build projects written in C#, Ruby, Scala, and other languages. It allows developers to create projects, dependencies and documentation using Project Object Model and plugins.
Why do we use Maven?
Maven is the latest build testing tool and a project management tool.
It makes the build process very easy (No need to write long scripts).
It has a standard directory structure which is followed.
It follows Convention over Configuration.
It has a remote maven repository with all the dependencies in one place that can be easily downloaded.
Can be used with other programming languages too, just not Java.
Hope, this now gives a clear view of Maven. Now let’s create a new Maven project using Intellij Idea IDE.
Open your IntelliJ IDE and go to the File ➜ New ➜ Project as shown in the below image.
A new project pop-up will be displayed on the screen, and we must enter the project’s details here.
Details required to create the Maven project are:
Name: Provide a suitable name as per your requirement.
Location: Choose the location where you want to store your project.
Language: Choose the programming language as per your requirement.
Build System: Here you have to choose Maven.
JDK: Choose the JDK you want to use. (Note: Maven uses a set of identifiers, also called coordinates, to uniquely identify a project and specify how the project artifact should be packaged.)
GroupId: a unique base name of the company or group that created the project
ArtifactId: a unique name for the project.
Simply, click on the Create button and the Maven project will be created.
After successfully creating the project we can see the structure of the Maven project. Some default files have been created as given in the image below.
Yes !! We have successfully created our Maven project. Let’s move ahead.
Step 4: Add dependencies in POM.xml file and Add .crx file in the resources package.
We shall include Maven dependencies in your project using IntelliJ IDEA. These dependencies need to be mentioned in our pom.xml file for our project build-up.
Below are the dependencies that we need to add to the pom.xml file.
selenium-java: Selenium WebDriver library for Java language binding
cucumber-java: Cucumber JVM library for Java language binding.
webdrivermanager: library to automatically manage and set up all the drivers of all browsers which are in test scope.
After adding dependencies in the pom.xml file we have to add the .crx file to the resources directory, .crx file is the file that we have generated in step 2.
To add the .crx file to the resources directory, copy the file from the file explorer and paste it into the resources directory. We can also rename the .crx file as we want.
For renaming the file, right-click on the file ➜ select the refactor option ➜ then click on the rename option.
As shown in the above image, the rename pop-up will flash on the screen. Here we can give the file name as desired.
Here in this project, I am renaming the .crx file with the CalculatorExtension.crx file.
Step 5: Create Packages and files in the project to automate chrome extension.
After adding dependencies to the pom.xml file. We have to create a BDD framework that includes packages and files. Before moving ahead, let’s first get an overview of the Cucumber BDD framework.
What is the Cucumber Behavior Driven Development (BDD)Framework?
Cucumber is a Behavior Driven Development (BDD) framework tool for writing test cases. It is a testing tool that supports Behavior Driven Development (BDD). It offers a way to write tests that anybody can understand, regardless of their technical knowledge. In BDD, users (business analysts and product owners) first write scenarios or acceptance tests that describe the behavior of the system from the customer’s perspective. These scenarios and acceptance tests are then reviewed and approved by the product owners. The Cucumber framework uses Ruby as programming language.
To manage our code files for the project we need to create packages that are as follows:
Features Package – All feature files are contained in this package.
Steps Package – All step definition files are included in this package.
Pages Package – All page files are included in this package.
Utilities Package – All configuration files are included in this package.
Now, we have to create a feature file,
5.1: Creating Features File:
Features file contains a high-level description of the Test Scenario in simple language. It is known as Gherkin. Gherkin is a plain English text language
Cucumber Feature File consists of following components –
Feature: We use “Feature” to describe the current test script that needs execution.
Scenario: We use Scenario to describe the steps and expected outcome for a particular test case.
Given: We use “Given” to specify the context of the text to be executed. We can parameterize steps by using data tables “Given”
When: “When” indicates the test action that we have to perform.
Then: We represent the expected outcome of the test with “Then”
We need to add the below code in the feature file for our project.
Feature: Calculator Extension
Scenario: User want to add 2 number by using calculator extension
Given User clicks on the extension icon
And User clicks on the calculator extension
When User clicks on number 9
And User clicks on "+" operator
And User clicks on number 2
And User clicks on "=" operator
Then User sees the result 11
According to the above feature file, we are adding two numbers. To open the Chrome WebDriver and add a calculator extension, we use a GIVEN file. With the use of ‘WHEN’ and ‘AND’ annotations, we are executing click actions on the calculator extension, with which we are adding two numbers from the calculator. In the final step, we are using the ‘THEN’ annotation to verify the result (the addition of two numbers).
5.2: Creating Steps file.
Steps Definition to automate chrome extension-
Step definition maps the Test Case Steps in the feature files (introduced by Given/When/Then) to code. It executes the steps on Application Under Test and checks the outcomes against expected results. For a step definition to execute, it requires matching the “Given” component in a Feature.
Here in the step file, we are mapping the steps from the feature file. In simple words, we are making a connection between the steps of the feature file and with step file. While mapping the steps we have to take care about the format of mapping the steps in step definition. We need to use the below format to map the steps for the feature we had created in the features file.
package Steps;
import Pages.CalculatorPage;
import Utilities.TestContext;
import io.cucumber.java.en.And;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;
import java.awt.*;
public class CalculatorStep extends TestContext {
CalculatorPage calculatorPage;
public CalculatorStep() throws AWTException { calculatorPage = new CalculatorPage(driver); }
@Given("User clicks on the extension icon")
public void User_clicks_on_the_extension_icon() throws InterruptedException {
calculatorPage.User_clicks_on_the_extension_icon();
}
@And("User clicks on the calculator extension")
public void userClicksOnTheCalculatorExtension() throws InterruptedException {
calculatorPage.userClicksOnTheCalculatorExtension();
}
@When("User clicks on number {int}")
public void User_clicks_on_number(int number) throws InterruptedException {
calculatorPage.User_clicks_on_number(number);
}
@And("User clicks on {string} operator")
public void userClicksOnOperator(String operator) throws InterruptedException {
calculatorPage.userClicksOnOperator(operator);
}
@Then("User sees the result {int}")
public void userSeesTheResult(int result) throws InterruptedException {
calculatorPage.userSeesTheResult(result);
}
}
5.3: Creating Page Object Design Pattern
Till now we have successfully created a feature file and a step file. Now in this step, we will be creating a page file. Page file contains all the logic of the test cases. Generally, in Web automation, we have page files that contain the locators and the actions to perform on the web elements but in this framework, we are not using the locators because as we know extension is not in the DOM(Document Object Model) element as it is outside the DOM element. So we will only create the methods and for those methods, we will be using Robot class and X and Y coordinates.
Here in this code, we are performing the activities that are hovering by the mouse actions(move, press, release), clicking on the calculator extension, clicking on the two numbers from the calculator, clicking on the calculator’s “+” addition operator, and obtaining the result of the addition of those two numbers.
What is the Robot Class in Selenium?
Robot Class in Selenium is used to enable automated testing for implementations of the Java platform. It generates input events in native systems for test automation, self-running demos, and other applications where users need control over the mouse and keyboard. Selenium Webdriver was unable to handle these pop-ups or applications and extensions. So a robot class was introduced in Java versions 1.3 and above, that can handle OS pop-ups or applications and extensions.
Robots help in managing all the activities like performing the task within the specified time, handling the mouse functions and the keyboard functions, and many more
While we are using the robot class, it requires the x and y coordinates of the element of the screen on which we will be performing the actions i.e hovering the cursor and then performing click actions.To find the coordinates we are using the Mofiki’s Coordinate finder.
What is Mofiki’s Coordinate Finder?
Mofiki’s Coordinate Finder finds out the present x and y coordinates of our cursor by hovering the mouse anywhere on the screen with the help of the application Mofiki’s Coordinate Finder, which is available for free download.
Steps to download and use Mofiki’s Coordinate Finder:-
Download the zip file of Mofiki’s Coordinate Finder application
Extract the Mofiki’s Coordinate Finder zip file and install the application setup.
Now open the Mofiki’s Coordinate Finder application. Use the image below as an illustration.
Now to find the x and y coordinates move the cursor to the point and just press the space bar we can get the x and y coordinates
package Pages;
import Utilities.TestContext;
import org.openqa.selenium.WebDriver;
import java.awt.*;
import java.awt.event.InputEvent;
import java.util.Objects;
public class CalculatorPage extends TestContext {
public CalculatorPage(WebDriver driver) throws AWTException {
TestContext.driver = driver;
}
public Robot robot = new Robot();
public void User_clicks_on_the_extension_icon() throws InterruptedException {
Thread.sleep(5000);
robot.mouseMove(1250, 48);
Thread.sleep(2000);
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
}
public void userClicksOnTheCalculatorExtension() throws InterruptedException {
Thread.sleep(3000);
robot.mouseMove(1000, 190);
Thread.sleep(2000);
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
Thread.sleep(10000);
}
public void User_clicks_on_number(int number) throws InterruptedException {
Thread.sleep(3000);
if(number == 0){robot.mouseMove(964, 450);}
else if (number == 1) {robot.mouseMove(969, 390);}
else if (number == 2) {robot.mouseMove(1020, 391);}
else if (number == 3) {robot.mouseMove(1087, 395);}
else if (number == 4) {robot.mouseMove(964, 334);}
else if (number == 5) {robot.mouseMove(1023, 336);}
else if (number == 6) {robot.mouseMove(1080, 334);}
else if (number == 7) {robot.mouseMove(965, 282);}
else if (number == 8) {robot.mouseMove(1023, 278);}
else if (number == 9) {robot.mouseMove(1089, 278);}
else { System.out.println("Number Invalid"); }
Thread.sleep(2000);
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
Thread.sleep(10000);
}
public void userClicksOnOperator(String operator) throws InterruptedException {
Thread.sleep(3000);
if(Objects.equals(operator, "+")){robot.mouseMove(1139, 446);}
else if (Objects.equals(operator, "-")) {robot.mouseMove(1137, 386);}
else if (Objects.equals(operator, "*")) {robot.mouseMove(1137, 331);}
else if (Objects.equals(operator, "/")) {robot.mouseMove(1138, 272);}
else if (Objects.equals(operator, "=")) {robot.mouseMove(1199, 446);}
else {System.out.println("Invalid Operator");}
Thread.sleep(2000);
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
Thread.sleep(10000);
}
public void userSeesTheResult(int result) {
System.out.println("Result should be "+ result);
}
}
5.4: Creating TestContext File.
Now, In the Utilities package we have to create a TestContext file in which we can declare a webdriver. Declaring the webdriver as public allows initialization in every class file after inheriting the TestContext class. The step file and page file inherit the testContext class file. Also, we have declared Robot class here.
package Utilities;
import org.openqa.selenium.WebDriver;
import java.awt.*;
public class TestContext {
public static WebDriver driver;
public static Robot robot;
}
5.5: Creating BaseStep File:
This step is very important because we will be creating an environment file (i.e. Hooks file) and also we are using Chrome Options to add Calculator extensions.
Before moving ahead let’s understand about Before and After Hook and Chrome Options
What is Before and After Hooks?
Hooks allow us to better manage the code workflow and help us reduce code redundancy. We can say that it is an unseen step, which allows us to perform our scenarios or tests.
@Before – Before hooks run before the first step of each scenario.
@After – Conversely After Hooks run after the last step of each scenario even when steps fail, are undefined, pending, or skipped.
What are Chrome Options?
For managing different Chrome driver properties, Selenium WebDriver has a concept called the Chromeoptions Class. For modifying Chrome driver sessions, the Chrome options class is typically combined with Desired Capabilities. Eventually it enables you to carry out numerous tasks, such as launching Chrome in maximized mode, turning off installed extensions, turning off pop-ups, etc.
At this instant we have to create Before and After Hooks. At the same time each hook should contain a void method as shown in the below code.
In the Before Hook, we have to initialize the webdriver. Also, we have to add simple lines of code to add extensions to the webdriver. To add the extensions we are using Chrome Options to Automate Chrome Extension. Then in the After Hook, we are closing the webdriver.
Now, we have to create a Base Step which should have driver configuration and hooks
package Utilities;
import io.cucumber.java.After;
import io.cucumber.java.Before;
import io.github.bonigarcia.wdm.WebDriverManager;
import org.openqa.selenium.chrome.ChromeOptions;
import java.io.File;
public class BaseStep extends TestContext{
@Before
public void initCucWeb()
{
ChromeOptions options = new ChromeOptions();
options.addExtensions(new File("src/test/Resources/CalculatorExtension.crx"));
options.addArguments("--remote-allow-origins=*");
options.setCapability(ChromeOptions.CAPABILITY,options);
driver = WebDriverManager.chromedriver().capabilities(options).create();
driver.manage().window().maximize();
}
@After
public void closeWeb()
{
driver.quit();
}
}
Please find attached the GitHub repository link. I have uploaded the same project to this repository. I have also attached a Readme.md file that explains the framework and the different commands we have used so far in this project.
It is a very difficult task to add an extension to a web driver and perform an action on extension icons. So basically, in this article, we have found a solution to add an Automate Chrome Extension to Webdriver and to perform a Click action on the extension icon apart from learning to Automate Chrome extension using the Selenium Webdriver.
The software testing landscape has evolved towards automation to meet the demands for quick and frequent deployments, adapting efficiently to constant updates and tight deadlines in a dynamic development environment.
I am an SDET Engineer proficient in manual, automation, API, Performance, and Security Testing. My expertise extends to technologies such as Selenium, Cypress, Cucumber, JMeter, OWASP ZAP, Postman, Maven, SQL, GitHub, Java, JavaScript, HTML, and CSS. Additionally, I possess hands-on experience in CI/CD, utilizing GitHub for continuous integration and delivery. My passion for technology drives me to constantly explore and adapt to new advancements in the field.
The purpose of this blog is to provide a step-by-step guide on how to use Visual Studio Code for Java Selenium Automation as the Integrated Development Environment (IDE) for designing and running Selenium tests with Java. Visual Studio Code is a defacto IDE for JavaScript, however, it is rarely used for Java and Selenium automation as traditionally test automation engineers use either Eclipse or IntelliJ IDEA. Being one of the most widely used IDEs, software professionals prefer Visual Sstudio Code for its functionality.
Cross-platform support: Visual Studio Code can run on Windows, macOS, and Linux
IntelliSense: Visual Studio Code provides intelligent code completion and error detection, making it easier to write and debug code
Built-in Git integration: Visual Studio Code provides built-in support for Git, allowing you to easily version control your projects
Extensible with plugins: Visual Studio Code has a large community of developers who have created a variety of plugins to enhance the functionality of the IDE.
Fast and lightweight: The design of Visual Studio Code focuses on being fast and lightweight, making it easy to use on lower-end hardware.
Free and open-source: Visual Studio Code is free and open-source, making it accessible to everyone.
Debugging and testing: Visual Studio Code has built-in support for debugging and testing, making it easier to identify and fix bugs in your code.
Customization: You can customize Visual Studio Code with themes, keybindings, and settings, allowing you to tailor the IDE to your needs.
Here’s what you’ll need to get started with using Visual Studio Code for Java Selenium Automation:
Once you’ve installed these components, you can create a new Java project in Visual Studio Code and add the Maven libraries to it.
Following the installation of these parts, you can use Visual Studio Code to build a new Java project and add the Maven libraries to your project.
Steps to setup in Visual Studio Code for Java Selenium Automation:
Assuming Visual Studio Code is installed, let’s start the recipe step by step to create a flow for execution.
Step 1:
You need to open Visual Studio Code and locate the Marketplace.
Step 2:
Go to the search bar search for Java then Install the Extension pack for Java from the Marketplace.
Step 3:
Now, Navigate to the settings option in the lower left corner.
Step 4:
Select the command palette and look for the command create Java project.
Step 5:
Probably, here we start how to add a maven repository into the project to run the Java-Selenium test using Visual Studio Code. After selecting Create Java Project, select the “Maven” option to help you create the project.
Step 6:
After that, it will navigate to the browse folder and choose a specific folder to create your Java project. Please select a folder and open it in Visual Studio Code.
Step 7:
The screen below will appear; enter your project name and press “Enter” to open that project in Visual Sstudio Code.
Step 8:
Once you open the project, you will see the default folder structure displayed. To ensure code reusability, we create the following framework in Visual Studio Code.
Default Structure
Hybrid Framework folder structure
Hybrid Driven Framework is a combination of both the Data-Driven and Keyword-Driven frameworks. Here, we externalize the keywords, as well as the test data. Furthermore, Keywords are maintained in a separate Java class file and test data can be maintained either in a properties file/excel file/can use the data provider of a TestNG framework.
Step 9:
So, for adding Maven dependencies and how to download them
Maven is a tool for managing or building projects. When various test engineers incorporate their files into the same framework, they use it to check for compilation problems amongst framework components. Consequently, every time we make a change to the framework, we update the build status and continuously maintain the monitor, framework components, or build. As a result, there are no compilation errors in the framework, it will output a “build success” message; otherwise, it will output a “build failure” message.
Once you select Maven Project, it will create a Maven project with a pom.xml file. In the pom.xml file, you need to add the selenium dependency from the website https://mvnrepository.com/ and add it into dependency.
This dependency has been added to provide the libraries required to run the Selenium project. In a normal Selenium project, we need to download standalone libraries and then add them to external libraries, whereas here, once you add this Maven dependency, it will automatically download all libraries required for the Selenium project.
In a Maven project, you can use the Apache POI library by adding its dependency to your project’s pom.xml file. This will automatically download and include the library in your project’s classpath. Once you have added the dependency, you can start using the Apache POI APIs in your Java code to read, write, and manipulate Microsoft Office documents.
In a Maven project, you can add the Extent Reports dependency to your project’s pom.xml file to use its reporting functionality. Once you have added the dependency, you can start using the Extent Reports APIs in your Java code to create and generate detailed reports for your automation test results.
In a Maven project, you can add the TestNG dependency to your project’s pom.xml file to use its testing functionality. Once you have added the dependency, you can start using the TestNG annotations in your Java code to define your tests, test suites, and test configurations.
In a Maven project, you can add the Log4j dependency to your project’s pom.xml file to use its logging functionality. Once you have added the dependency, you can start using the Log4j APIs in your Java code to log messages to various output targets. You can configure Log4j using a configuration file such as log4j2.xml or log4j2.properties, which specifies the logging level, output target, and other logging settings.
Here, you need to run Java-selenium tests by using the pom.xml file, according to your demand and test requirements, Therefore, you can add more maven repositories.
1. Test/Java/example:
This folder contains the test source code packages and classes. Here, this contains all the data related to test cases, including page objects, base classes, and the test case class, which helps run the whole TestNG framework. However, this contains all the data related to test cases, including page objects, base classes, and the test cases class, which help run the whole TestNG framework.
Code Explanation in Demo example:
Login Page:
The base class in the main class will take care of browser setup, loading configuration files, and other reusable methods like screenshots, handling sync issues, and many more.
Using Base, we can avoid code duplication.
Reuse code as much as we can.
package com.example.Pages;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
public class LoginPage {
WebDriver driver;
public LoginPage(WebDriver driver){
this.driver = driver;
PageFactory.initElements(driver, this);
}
@FindBy(id="email")
WebElement usernameBox;
@FindBy(id="passwd")
WebElement passwordBox;
@FindBy(name="SubmitLogin")
WebElement SignInBtn;
public void enterUsername(String uname){
usernameBox.sendKeys(uname);
}
public void enterPassword(String upwd){
passwordBox.sendKeys(upwd);
}
public void submitButton(){
SignInBtn.click();
}
}
Base Class:
@BeforeClass: The annotated method will be run before the first test method in the current class is invoked.
@AfterClass: The annotated method will be run after all the test methods in the current class have been run.
package com.example.TestCases;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import com.example.Utilities.ReadConfig;
public class BaseClass {
ReadConfig read = new ReadConfig();
public String googlebaseurl = read.getGoogleBaseURL();
public String loginbaseurl = read.getLoginBaseURL();
public String uname = read.getUsername();
public String upwd = read.getPassword();
public String SuccessURL = read.getSuccessURL();
public WebDriver driver;
public Logger logger;
@BeforeClass
public void SetUp(){
System.setProperty("webdriver.chrome.driver", "Drivers/chromedriver.exe");
// WebDriverManager.chromedriver().setup();
driver = new ChromeDriver();
driver.manage().window().maximize();
logger = Logger.getLogger("googledemo");
PropertyConfigurator.configure("log4j.properties");
}
@AfterClass
public void tearDown(){
driver.quit();
}
}
Test Class:
According to the below code, This class will help to run TestNG test cases and will give results. You can add third-party tools for generating reports as well such as extent reports, and Allure reports.
Basically, this folder is used to store browsers that will be required to run test cases on that specific browser. Whether it is Chrome, Edge, or Opera. Further includes driver information, where the Chrome Driver, Firefox, or Edge—whichever you’re comfortable with. Even you can use maven dependency for instantiating Webdriver. The WebDriverManager is a library that allows you to automate the management of WebDriver binaries. There are such as Chrome driver, gecko driver, etc. in your Java project.
3. Configuration:
The Above image implies that properties are used to externalize configurable data. Because if you put that data in your code (test script), you would need to build the code each time you wanted to modify the property’s value. As a result, the fundamental advantage of properties is that they may be modified at any time. And exist independently of your source code. Thus, a pair of strings is used to store each parameter, with one string serving as the key and the other as the value.
You can see the folder structure, where the configuration folder contains a config file that includes all the common information required to run a test.
4. Utilities:
Once we have the config file loaded, we need to read the properties of the config file. The Properties object gives us the .getPropertymethod that takes the key of the property as a parameter and returns it. Basically, the value of the matched key from the .properties file. Therefore, this includes a class that assists in reading all of the data from the config.properties file.
5. Screenshots:
A screenshot in Selenium WebDriver is there we can use for bug analysis. Selenium WebDriver can automatically take screenshots during the execution. But if users need to capture a screenshot on their own, they need to use the Take Screenshot method. So, which notifies the WebDriver to take the screenshot and store it in Selenium. As a result, it includes screenshots that we took at the time of running the test.
6. log4j.properties:
The above image log4j.properties is a configuration file that we can use with the Apache Log4j logging framework. As a result, which is a popular logging library for Java applications. Users utilize this file to configure the logging behavior of the application, including specifying the output destination for log messages. The format of log messages, and the logging levels for different categories of log messages. The log4j.properties file contains key-value pairs that define the various logging settings for the application.
Step 10:
Basically, here is how we organize the hybrid framework. We need to add a few folders to make it easier for testers to run code without encountering them.
Initially, you will not find any errors until you save your code in Visual Studio Code through ctrl+s. You can hover over that error and you will find a solution for that. If you need to install any package, Thus it will also be visible to you.
Run Test:
Navigate to the Project Directory:- Open a command prompt or terminal window. And navigate to the directory where your Maven project is located. This should be the directory that contains the “pom.xml” file, which is the Maven project configuration file.
Run Maven Test Command:- Once you are in the project directory, you can run the following command to execute the Maven tests: “mvn test”
This command will instruct Maven to run the tests defined in your Maven project. Maven will automatically compile the necessary source code and download dependencies. And execute the tests using a testing framework such as JUnit, TestNG, or any other testing framework that you have configured in your project’s dependencies.
View Test Results:- After the tests have been executed. The Maven will display the test results in the command prompt or terminal window. You can view the test results to see which tests have passed, failed, or skipped.
Video:
Accordingly, the below tutorial will guide you
Conclusion:
Since Visual Studio Code for Java Selenium m Automation is a well-known IDE among software professionals. Here, I can think of no better method to run Java-Selenium automation through VSCode.
However, It offers the best Java extension for using Visual Studio Code for Java Selenium Automation. Basically, we make run test cases more appropriate and adaptable.
Harish is an SDET with expertise in API, web, and mobile testing. He has worked on multiple Web and mobile automation tools including Cypress with JavaScript, Appium, and Selenium with Python and Java. He is very keen to learn new Technologies and Tools for test automation. His latest stint was in TestProject.io. He loves to read books when he has spare time.