In today’s fast-paced development world, debugging can easily become a dreaded task, so here is the complete guide to Debugging Java code in IntelliJ. You write what seems like perfect code, only to watch it fail mysteriously during runtime. Furthermore, maybe a NullPointerException crashes your app at the worst moment, or a complex bug hides in tangled logic, causing hours of frustration. Even with AI-powered coding assistants helping generate boilerplate, the need to understand and troubleshoot your code deeply has never been greater, especially when debugging Java code in IntelliJ.
For example, imagine spending a whole afternoon chasing an elusive bug that breaks customer workflows—only to realize it was a simple off-by-one error or a condition you never tested. This experience is all too real for developers, and mastering your debugging tools can mean the difference between headaches and smooth sailing when debugging Java code in IntelliJ.
That’s where IntelliJ IDEA’s powerful debugger steps in — it lets you pause execution, inspect variables, explore call stacks, and follow exactly what’s going wrong step by step. Whether you’re investigating a tricky edge case or validating AI-generated code, sharpening your IntelliJ debugging skills transforms guesswork into confidence.
This post will guide you through practical, hands-on tips to debug Java effectively with IntelliJ, ultimately turning one of the most daunting parts of development into your secret weapon for quality, speed, and sanity.
Why do we debug code?
When code behaves unexpectedly, running it isn’t enough — you need to inspect what’s happening at runtime. Debugging lets you:
Pause execution at a chosen line and then inspect variables.
Examine call stacks and then jump into functions.
Evaluate expressions on the fly and then change values.
Reproduce tricky bugs (race conditions, exceptions, bad input) with minimal trial-and-error.
Additionally, good debugging saves time and reduces guesswork. Moreover, it complements logging and tests: use logs for high-level tracing and debugging Java code in IntelliJ for interactive investigation.
Prerequisites for Debugging Java code in IntelliJ
IntelliJ IDEA (Community or Ultimate). Screenshots and shortcuts below assume a modern IntelliJ release.
JDK installed (e.g., Java 21 or whichever version your project targets).
A runnable Java project in IntelliJ (Maven/Gradle or a simple Java application).
Key debugger features and how to use them
1. Breakpoints
A breakpoint stops program execution at a particular line so you can inspect the state.
How to add a breakpoint: Click the gutter (left margin) next to a line number or press the toggle shortcut. The red dot indicates a breakpoint.
Breakpoint variants:
Simple breakpoint: pause at a line.
Conditional breakpoint: pause only when a boolean condition is true.
Right-click a breakpoint → “More” or “Condition”, then enter an expression (e.g., numbers[i] == 40).
Log message / Print to console: configure a breakpoint to log text instead of pausing (helpful when you want tracing without stopping).
Method breakpoint: pause when a specific method is entered or exited (note: method breakpoints can be slower — use sparingly).
Exception breakpoint: pause when a particular exception is thrown (e.g., NullPointerException). Add via Run → View Breakpoints (or Ctrl+Shift+F8) → Java Exception Breakpoint.
Example (conditional):
for (int i = 0; i < numbers.length; i++) {
System.out.println("Processing number: " + numbers[i]); // set breakpoint here with condition numbers[i]==40
}
Expected behavior: the debugger pauses only when the evaluated condition is true.
2. Watchpoints (field watch)
A watchpoint suspends execution when a field is read or written. Use it to track when a shared/static/class-level field changes.
How to set:
Right-click a field declaration → “Toggle Watchpoint” (or add in the Debug tool window under Watches).
You can add conditions to watchpoints too (e.g., pause only when counter == 5).
Note: watchpoints work at the field level (class members). Local variables are visible in the Variables pane while stopped, but you can’t set a watchpoint on a local variable.
3. Exception breakpoints
If an exception is thrown anywhere, you may want the debugger to stop immediately where it originates.
How to set:
Run → View Breakpoints (or Ctrl+Shift+F8) → + → Java Exception Breakpoint → choose exception(s) and whether to suspend on “Thrown” and/or “Uncaught”.
This is invaluable to find the exact place an exception is raised (instead of chasing stack traces).
Here’s an expanded and more practical version of those sections. It keeps your tone consistent and adds real-world examples, common use cases, and small code snippets where helpful.
You can connect IntelliJ to port 5005 and debug as if the app were local.
Common use case: Your REST API behaves differently inside Docker. Attach debugger → Set breakpoints in your service → Reproduce the issue → Inspect environment-specific behavior.
9. Debugging unit tests (Practical usage)
Right-click a test and run in debug mode. Useful for:
Verifying mocks and stubbing
Tracking unexpected NPEs inside tests
Checking the correctness of assertions
Understanding why a particular test is flaky
Example: Your test fails:
assertEquals(100, service.calculateTotal(cart));
Set a breakpoint inside calculateTotal() and run the test in debug mode. You instantly see where values diverge.
10. Logs vs Breakpoints: when to use which (Practical usage)
Use both together depending on the situation.
Use logs when:
You need a history of events.
The issue happens only sometimes.
You want long-term telemetry.
It’s a production or staging environment.
Use breakpoints when:
You need to inspect exact values at runtime
You want to experiment with Evaluate Expression
You want to track control flow step-by-step
Log Message Breakpoints (super useful)
These let you print useful info without editing code.
Example: Instead of adding:
System.out.println("i = " + i);
You can configure a breakpoint to log:
"Loop index: " + i
and continue execution without stopping. This is ideal for debugging loops or repeated method calls without cluttering code.
Example walkthrough (putting the pieces together)
Open DebugExample.java in IntelliJ.
Toggle a breakpoint at System.out.println(“Processing number: ” + numbers[i]);.
Start debug (Shift+F9). Program runs and pauses when numbers[i] is 40.
Inspect variables in the Variables pane, add a watch for i and for numbers[i].
Use Evaluate Expression to compute numbers[i] * 2 or call helper methods.
If you change a method body and compile, accept HotSwap when IntelliJ prompts to reload classes
Common pitfalls & tips
Method/exception breakpoints can be slow if used everywhere — prefer line or conditional breakpoints for hotspots.
Conditional expressions should be cheap; expensive conditions slow down program execution during debugging.
Watchpoints are only for fields; for locals, use a breakpoint and the Variables pane.
HotSwap is limited — don’t rely on it for structural changes.
Remote debugging over public networks: Be careful exposing JDWP ports publicly — use SSH tunnels or secure networking.
Avoid changing production behavior (don’t connect a debugger to critical production systems without safeguards).
Handy keyboard shortcuts (Windows/Linux | macOS)
Toggle breakpoint: Ctrl+F8 | ⌘F8
Start debug: Shift+F9 | Shift+F9
Resume: F9 | F9
Step Over: F8 | F8
Step Into: F7 | F7
Smart Step Into: Shift+F7 | Shift+F7
Evaluate Expression: Alt+F8 | ⌥F8
View Breakpoints dialog: Ctrl+Shift+F8 | ⌘⇧F8
(Shortcuts can be mapped differently if you use an alternate Keymap.)
Key Takeaways
Debugging is essential because it helps you understand and fix unexpected behavior in your Java code beyond what logging or tests can reveal.
IntelliJ IDEA offers powerful debugging tools like breakpoints, conditional breakpoints, watchpoints, and exception breakpoints, which allow you to pause and inspect your code precisely.
Use features like Evaluate Expression and Watches to interactively test and verify your code’s logic while paused in the debugger.
Stepping through code (Step Over, Step Into, Step Out) helps uncover issues by following program flow in detail.
HotSwap allows quick code changes without restarting, therefore speeding up the debugging cycle.
Remote debugging lets you troubleshoot apps running in containers, servers, or other environments thereby, enabling seamless investigation.
Combine logs and breakpoints strategically depending on the situation, therefore, to maximize insight.
Familiarize yourself with keyboard shortcuts and IntelliJ’s debugging settings ultimately, for an efficient workflow.
Conclusion
In fact, IntelliJ’s debugger is powerful — from simple line breakpoints to remote attachment, watches, exception breakpoints, and HotSwap. As a result, practicing these workflows will make you faster at diagnosing issues and understanding complex code paths. Debugging Java code in IntelliJ. Start small: set a couple of targeted conditional breakpoints, step through the logic, use Evaluate Expression, and gradually add more advanced techniques like remote debugging or thread inspection.
An SDET with hands-on experience in the life science domain, including manual testing, functional testing, Jira, defect reporting, web application, and desktop application testing. I also have extensive experience in web and desktop automation using Selenium, WebDriver, WinAppDriver, Playwright, Cypress, Java, JavaScript, Cucumber, maven, POM, Xray, and building frameworks.
In this blog, I’m going to share with you how to create executable Jar File for automation framework designed with Cucumber, Java, Selenium and Maven.
What is the executable jar file?
The executable jar file to execute Cucumber Scenarios includes all build structures files of the framework along with packages, and dependencies. That works as an execution of the test cases.
Why so we need a jar file?
We have a framework that contains numerous test cases.Instead of giving you the code, we’ll give you a tool that can run these tests and make reports customized for different needs like quick checks and in-depth checks. Sometimes, the client doesn’t want to see or understand how the framework works. They simply want the final reports like Allure, HTML, or PDF reports which help them assess the quality of the product. The client doesn’t require an IDE like IntelliJ or Eclipse, for instance. They just need a user interface where they can click a button to generate the reports. This approach helps reduce their complexity. In such scenarios, we need a JAR file. This JAR file facilitates the triggering of test cases according to specific Cucumber tags and generates the necessary reports.
Technology used for this project (Executable jar file)
In the software testing world, the commonly used tool is selenium. Most of the creators used this stable and compatible tool for Automation.
Selenium: The software testing community has had faith in Selenium since 2004, as it’s been a reliable tool for testing. Most of us are familiar with selenium. If you are a beginner, please check out here.
Maven: The maven is a build management tool. Maven builds and manages Java-based projects. Maven provides an easy way to share the JARs across several projects. If you want to know more about Maven please check out here
Java: We are using the programming language Java for this project.
Cucumber: Cucumber supports behavior-driven development as a tool.
Prerequisites for the project (Executable jar file)
The following tools might have been installed on your system to executable jar file.
Java: Please check, is jdk installed on your system? If you cannot find the Java version on your system, please check out here to install Java.
Maven: Please check, is maven installed on your system? If you could not find the maven version on your system, please check out here to install maven.
Cucumber: When you create the maven project, you need to add cucumber plugins in the project setting window. If you wish to explore the cucumber in detail, here is the link Link you can refer to.
Framework Overview of Bdd Cucumber project
I am assuming you know the basic Bdd cucumber project architecture. For the creation of a jar, we need to modify the folder structure. Here I am highlighting the required files and key factors.
Let’s see the framework folder structure.
When we created the new project for the executable jar file, we could see the simple folder structure provided by Maven.
SRC Folder: The SRC folder is the parent folder of a project that will include the main and test folders. For the QA environment, normally we are using the test folder. The main folder is used for the development environment. The created jar contains all files inside the src folder.
Test Folder: Inside the test folder, Java and resources folders are available.
Java Folder: This folder contains the Java classes where the actual code is present.
Resources Folder: The Resources folder contains the resources file, test data file, and document files.
Pom.xml: In this file, we are managing the dependencies and plugins that are required for automation.
Structure of the Test Folder
The test folder design is the base of the executable jar file creation for the cucumber framework. Inside the java folder, we have to create a directory (org.BDD). In this directory, we need to create a subdirectory on the basis of code design Let’s see the subdirectory
1. Core
The core folder contains a subfolder. In the core folder, we set the standard code like…
Hooks: This Java class contains the basic before and after functions. These functions are set for the browser initialization and termination. Also, we can set the before and after methods, steps, and scenarios as per project requirements.
package org.CBDD.core;
import io.cucumber.java.After;
import io.cucumber.java.Before;
import io.cucumber.java.Scenario;
import org.CBDD.utilities.WebUtil;
public class Hooks extends TestContext {
@Before
public void beforeScenario(Scenario scenario) {
driver = WebUtil.initWebDriver();
}
@After
public void afterScenario() {
WebUtil.tearDown();
}
}
Main: While executing Java programs, by default, the JDK calls the Main functions. For the execution of a jar, we need the java command, hence we need to define the main class in our framework.
package org.CBDD.core;
public class Main {
public static void main(String[] args) throws Throwable {
String[] arguments = {};
io.cucumber.core.cli.Main.run(arguments);
}
}
TestContext: The TestContext Java class is used to define instances of classes and declare global variables. Here, Java classes extend the TestContext class and inherit the properties and values of the content.
package org.CBDD.core;
import org.openqa.selenium.WebDriver;
import org.CBDD.pages.CalculatorPage;
public class TestContext {
public static WebDriver driver;
public static CalculatorPage calculatorPage;
}
TestRunner: The Java class contains the @CucumberOptions properties. In the TestRunner class, we define the glue between the step definitions and feature files. In the case of BDD, this TestRunner class plays an important role.
package org.CBDD.core;
import io.cucumber.testng.AbstractTestNGCucumberTests;
import io.cucumber.testng.CucumberOptions;
import org.testng.annotations.DataProvider;
@CucumberOptions(features = "classpath:Features",
glue = {"org.CBDD"})
public class TestRunner extends AbstractTestNGCucumberTests {
@DataProvider
@Override
public Object[][] scenarios() {
return super.scenarios();
}
}
2. Steps:
The Steps folder contains the Java classes for step definitions. In this folder, we need to specify the path in the glue option of the @CucumberOptions annotation so that the feature files can detect the step definitions during execution. If the glue is not properly mentioned, an ‘undefined step’ error will occur.
Inside the Steps folder, each Java class contains the implementations of the steps as defined in the feature files.
package org.CBDD.steps;
import org.CBDD.core.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 org.testng.Assert;
import org.CBDD.pages.CalculatorPage;
import java.io.IOException;
public class CalculatorSteps extends TestContext {
public CalculatorSteps() {
calculatorPage = new CalculatorPage();
}
@Given("I am on Calculator page")
public void iAmOnCalculatorPage() throws IOException {
calculatorPage.iAmOnCalculatorPage();
}
@When("I enter number {int}")
public void iEnterNumber(int number) {
calculatorPage.iEnterNumber(number);
}
@And("I click on operator {string}")
public void iClickOnOperator(String operator) {
calculatorPage.iClickOnOperator(operator);
}
@Then("I verify the result as {int}")
public void iVerifyTheResultAs(int expectedResult) {
String actualResult = calculatorPage.iVerifyTheResultAs();
Assert.assertEquals(actualResult, String.valueOf(expectedResult));
}
}
3. Pages:
The Pages folder contains the page classes that house the actual code. The page functions are called in the step class.
package org.CBDD.pages;
import org.CBDD.core.TestContext;
import org.openqa.selenium.By;
import org.CBDD.utilities.ConfigUtil;
import java.io.IOException;
public class CalculatorPage extends TestContext {
public void iAmOnCalculatorPage() throws IOException {
driver.get(ConfigUtil.getPropertyValue("base_url"));
}
public void iEnterNumber(int number) {
driver.findElement(By.xpath("//span[@onclick='r(" + number + ")']")).click();
}
public void iClickOnOperator(String operator) {
driver.findElement(By.xpath("//span[@onclick=\"r('" + operator + "')\"]")).click();
}
public String iVerifyTheResultAs() {
driver.findElement(By.xpath("//span[@onclick=\"r('=')\"]")).click();
return driver.findElement(By.xpath("//div[@id='sciOutPut']")).getText().trim();
}
}
4. Utilities:
The Utilities folder contains utilities to reduce the repetition of code. It includes the WebUtil class, which contains functions for browser initialization and termination.
package org.CBDD.utilities;
import io.github.bonigarcia.wdm.WebDriverManager;
import org.CBDD.core.TestContext;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
public class WebUtil extends TestContext {
public static WebDriver initWebDriver() {
WebDriverManager.chromedriver().setup();
driver = new ChromeDriver();
driver.manage().window().maximize();
return driver;
}
public static void tearDown() {
driver.quit();
}
}
5. Resources:
Normally, this folder is used to store resources such as test data, properties, and configuration files. In this case, we need to declare the feature files inside the resources folder because the created target folder contains a non-editable feature folder. This setup ensures that feature files are correctly packaged and accessible during the build process.
Features: Features contain the feature files. We need to provide the path of this folder in glue. Here we provide the path “classpath:Features” beecause, the jar does not contain the absolute path. @cucumberOptions(features = “classpath:Features”, glue = {“org.CSDD”}) In the feature file, we use the Gherkin language to write test cases.
Feature: Verify Calculator Operations
@addsub
Scenario Outline: Verify addition and subtraction of two numbers
Given I am on Calculator page
When I enter number <number>
And I click on operator '<operator>'
And I enter number <number1>
Then I verify the result as <expectedResult>
Examples:
| number | operator | number1 | expectedResult |
| 5 | + | 2 | 7 |
| 9 | - | 3 | 6 |
@muldiv
Scenario Outline: Verify multiplication and division of two numbers
Given I am on Calculator page
When I enter number <number>
And I click on operator '<operator>'
And I enter number <number1>
Then I verify the result as <expectedResult>
Examples:
| number | operator | number1 | expectedResult |
| 6 | * | 4 | 24 |
| 2 | / | 2 | 1 |
Cucumber.properties: This properties file is used to set the Cucumber configuration. Normally during the execution, this file is detected by Cucumber automatically and the configuration is implemented. The same configuration can be set in the TestRunner class. In the case of CI/CD execution or jar execution, the priority goes to the cucumber.properties file rather than the TestRunner class. Hence, we need to implement the same configuration in both the TestRunner class and the cucumber.properties file.
cucumber.publish.enabled:true
CUCUMBER_PUBLISH_TOKEN:0b5c7164-ab9e-43ed-b6ba-da66c5e07c02
cucumber.features= Features
cucumber.glue=org.CBDD.core,org.CBDD.steps
Manifest file: This file is the most important file for executing the jar file. The manifest file by default houses the META-INF folder. This file contains information about the files packaged in a JAR file. This manifest file specifies the Main class and the jar packages that are available in the External Libraries folder. The purpose of having a manifest file is to specify the main class, which is easily detected by the JAR during execution. Without a manifest file, the JAR cannot identify the main class; hence, the JDK is confused about selecting the execution entry point.
How to add Manifest file in project folder structure
For adding the manifest file to your project, there are two ways.
Add the manifest file from the project settings.
Assuming you are using the IntelliJ IDEA editor, follow the procedure below:
Click on the File menu and select Project Settings.
Click on the file menu and select the project setting
Select the artifacts from the project structure screen
Click on ‘+’ icon, select the jar option -> form module with dependencies
Select the main class -> select the checkbox of ‘copy to the output directory and link via manifest’ -> enter the directory for META-INF/MANIFEST.MF as ‘project directory + src\test\resources’
Click on the Apply button and the OK button
You can see the manifest file stored in your resources folder.
Add the manifest file with the org.apache.maven.plugins
Here, we need to add the Maven plugin to the pom.xml file. In this plugin, we need to mention the path where the manifest file is stored and the Main class package.
<build>
<plugins>
<plugins>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.3.0</version> <!-- Use the latest available version -->
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>src/test/resources/</classpathPrefix>
<mainClass>org.CBDD.core.Main</mainClass>
</manifest>
</archive>
</configuration>
</plugins>
</plugins>
</build>
6. POM.xml File
Maven has the pom.xml file that contains information about the project and configuration details. It contains the default architecture for most projects.
Project dependencies configuration is specified in the pom.xml file as per requirement. We have added the plugins provided by Maven as per our project needs and configuration.
Let’s see some required plugins for jar creation.
Maven-jar-plugin: This plugin provides the capability to build the jar. It helps to create a jar for test classes of the project. In this plugin, we need to mention the manifest file path that will decide the main class of the jar file. We can check the latest version of this plugin on the Maven repository. In case, you are having a problem setting the plugin, you can go with the maven-jar-plugin dependencies.
Maven-dependency-plugin: When we create the jar, we will see it in the target folder. The jar file contains the manifest file and packages inside the jar directory or target folder. Hence, this plugin comes into the picture. The plugin copies all dependencies or packages from the pom.xml file and stores them in the jar directory folder (target folder). During execution, the jar requires these dependencies/packages/jars.
Maven-resources-plugin: The resources folder contains the test data, properties, and document files. Without this plugin, when we create the jar, the jar doesn’t contain the files from the resources folder. In case we need to provide these files externally to the jar. So, to avoid this painful process, we can use this plugin. This plugin works by copying all files from the resource folder into the jar files. After the creation of the jar file, we can check the availability of this file in the command prompt with this command: “Jar tf file.jar”
As you have followed the above process and configuration, we can proceed with jar creation. We can create the jar in two ways.
Create a jar with the help of the command: ‘mvn package’
In your project directory, open the terminal. Maven has a command to create a jar, which is ‘mvn package’. When you execute this command, it starts the process of creating the JAR and runs your test cases. After the completion of this process, you will find the jar file in the target folder.
Create the jar file with maven lifecycle steps
In your IntelliJ IDEA, there is an E-Maven tab. This tab includes the Lifecycle sub-tab.
Follow this process:
Clicks on the lifecycle tab and follow below diagram.
Execution of jar file
Once you successfully create the JAR along with the dependencies in the target folder, you can use some commands related to the JAR file.
Check the directories in jar file
To check the directories included in a jar file, you can use the command ‘jar tf filename.jar’. This command will list all the files and directories contained within the jar file.
Output:
Run the jar file
Normally, when we run a jar file, the jar file starts with the main class. Whatever configurations the main class includes, those files will execute. The command to run a jar file is: Java jar jarFileName.jar
Output:
Run the specific test case from jar
Normally, we execute the smoke or regression test cases. We differentiate the test cases by tag name. In this project, we have two scenarios with the tags “@addsub” and “@muldiv.”
Based on the tags, we can select the test cases for execution. Open the terminal and change the directory to the target folder. The command for execution is as follows: java -cp jarFileName.jar io.cucumber.core.Main featurefileName –tags “@tagname”
The creation of a jar file for a Cucumber Maven framework, as described, represents a strategic approach that offers flexibility in executing test cases directly from the jar file. This JAR file helps minimize issues related to redundant code and ensures stable and customized execution.
In conclusion, creating a jar with Selenium, Java, and BDD using Cucumber helps deliver high-quality software. By following best practices like designing a robust framework architecture, leveraging Maven plugins, and configuring the cucumber.properties file, we can generate an executable JAR file for effective automation testing.This enhances the stability of the test cases and reduces the failure rate.
Source Code:
Wish to take a look at the source code? You can attain a clearer and more straightforward understanding by visiting the repository at the following URL, where you’ll find a comprehensive guide that outlines the steps to follow. https://github.com/spurqlabs/JAR-File-Creation-
Click here to read a more blogs to increase your software testing skills.
An SDET with hands-on experience in the life science domain, including manual testing, functional testing, Jira, defect reporting, web application, and desktop application testing. I also have extensive experience in web and desktop automation using Selenium, WebDriver, WinAppDriver, Playwright, Cypress, Java, JavaScript, Cucumber, maven, POM, Xray, and building frameworks.
In the realm of automation testing, the conventional practice of identifying locators such as XPath, CSS, and ID is widely employed. However, there are scenarios where substantial time is expended in locating elements within diverse components, such as popup windows and Microsoft Foundation Class (MFC) windows. Additionally, there are cases where element location proves to be impossible. These challenges often impede progress and create bottlenecks. Hence, here in this blog, my aim is to propose a solution for addressing these issues and optimizing time allocation.
What if there was a way to bypass the traditional locator-finding technique and still identify and interact with elements?
Well, it is indeed possible using Sikuli. Sikuli offers an alternative approach to automation by leveraging visual patterns, allowing users to interact with elements on the screen without relying on traditional locator-based techniques.
Let’s understand What is Sikuli:
Sikuli is an open-source and powerful test automation tool that excels when there is limited access to a GUI’s internal or source code. Instead of relying on XPath, CSS, or ID, Sikuli employs image recognition and GUI component control to identify objects displayed on the screen. It is operate as a separate tool to employees’ image recognition mechanism with some action perform on the element.
Sikuli is a versatile tool that integrates seamlessly with popular programming languages like Python and Java. It is compatible with various operating systems, including Windows, Mac, and Linux as well as integrating with Selenium and Pycharm. By adopting this approach, we significantly reduce the time required for element location, simplifying the automation process.
Pre-requisite For Sikuli:
To get started using Sikuli, we need to install the following things.
Download and Installed any IDE as per your preference. Here we are using Intellij Idea
Install Other required dependencies like selenium, web driver, etc
Create a folder to store screenshots in a project.
To take a screenshot, you can use a built-in snippet tool available on your system. Alternatively, you can install tools like Inspector, PowerShell, or AutoIT, which provide x and y coordinates. For more information on these tools, you can refer to this blog: https://spurqlabs.com/different-tools-to-inspect-desktop-app-elements/
Using x and y coordinates, we take a screenshot during execution and store it in a specific path. We have written the code below:
Create one Java class.
Build your project.
Architecture of Sikuli:
Sikuli is a framework that assists in automating various elements on web pages.
The framework utilizes an image recognition mechanism to identify elements on a webpage.
Image recognition is achieved by comparing the elements on the webpage with provided images.
If a provided image is not found on the webpage, Sikuli raises an exception.
In specific scenarios, it is advisable to select an appropriate image that precisely highlights a single element on the webpage.
Selecting a precise image helps to ensure greater accuracy in element identification.
The Sikuli framework offers different methods to execute actions on web pages.
These methods provide versatility and flexibility in achieving automation objectives.
Screen Class:
The Sikuli framework has an inbuilt Screen class, a predefined method for performing actions on web elements using images. To access methods of the Screen class, we need to declare a reference to this class and initialize it.
Screen screen = new Screen();
In the above code, the variable “screen” is declared as an instance of the Screen class, and the new keyword is used to create a new object of the Screen class.
Here are some of the methods available in the Screen class that can be used efficiently:
Click on Element- Image:
To perform a left click on an element, provide an image to locate/identify the element to be clicked.
Ex: screen.click(“image path”);
Right-click on the element:
This method is used to perform a right-click on an element by providing an image to locate/identify the element to be clicked.
Ex: s.rightClick(“Image Path”);
Double-click on the element:
We use this method to perform a double-click action on an element. It first locates the element on the screen and then performs a double left click on the element.
Ex. s.doubbleClick(“Image Path”);
Type on Element :
In the Sikuli framework, you use the Type method to send Keys by providing an image path and sending text as a method argument.
Ex: screen.type(“Image path”, ”Send Key”);
Find() :
We can use this method to check the element’s visibility on a webpage.
EX. screen.find(“Image Path”);
DragDrop :
Users use this method to perform the action as drag and drop. We provide a source image and target image to the drag-drop method argument.
In the world of automation testing, we use an Integrated Development Environment (IDE) to write code. Nowadays, it has become common to create Maven projects to facilitate collaboration with various add-ons. As a widely used automation tool, Selenium supports integration with many add-ons. To integrate Sikuli into the Selenium framework, we need to add the required dependencies in the pom.xml file of our project.
To find the Sikuli dependencies, we can search the Maven repository at https://mvnrepository.com/artifact/org.sikuli. From this repository, we can copy the necessary dependencies and paste them into the pom.xml file of our project.
By adding the Sikuli dependencies to the pom.xml file, we ensure that the required libraries and resources are properly imported and utilized within our Selenium-Sikuli integration. This allows us to leverage the capabilities of Sikuli for image recognition and interaction within our Selenium automation framework.
We are creating sikuli funcion
1. Create a maven project, create a class with the main method where a set a browser and launch a browser:
public static void main (String [] argos){
WebDriverManager.chromedriver().setup();
ChromeDriver driver = new ChromeDriver();
driver.get(“https://demoqa.com/”);
driver.manage().window().maximize();}
2. Take a screenshot and store it in a specific location:
We are well aware that the Snipping Tool is a reliable tool for capturing screenshots. By utilizing this tool, we can capture customized screenshots and save them within the project. folder.
From the above image, we are cropping a single element image and saving it in the project screenshot folder.
How to take screenshots by using x,y coordinates:
There is an alternative method to capture screenshots without relying on external tools.
We can utilize the Robot class and its methods to capture screenshots based on x and y coordinates.
To capture a rectangular screenshot, we need two sets of x and y coordinates.
The first set represents the top-left corner of the rectangle, and the second set represents the bottom-right corner.
By specifying these coordinates, we can define the area of the screen to capture.
An example code snippet captures a screenshot based on the specified coordinates.
Our framework saves the captured screenshot to a specific location.
String fileName1 = "";
try {
Robot robot = new Robot();
String imgeFormat = ".png";
StringBuilder str = new StringBuilder("imageFolderPath" +
System.currentTimeMillis() + image format);
fileName1 = str.toString();
Rectangle captureRect = new Rectangle(xStart, yStart, xEnd - xStart, yEnd - yStart);
BufferedImage screenFullImage = robot.createScreenCapture(captureRect);
format = "png";
System.out.println(" Path is " + fileName1);
ImageIO.write(screenFullImage, format, new File(fileName1));
System.out.println("A partial screenshot saved!");
} catch (AWTException | IOException ex) {
System.err.println(ex);
}
Explanation of the above code:
Declares a variable fileName1 of type String and initializes it as an empty string.
The try-catch block handles potential exceptions that may occur during execution.
Creates a new instance of the Robot class, which allows for programmatic control of the mouse and keyboard
Declare an image format variable that assigns value as ‘.png’
Constructs a StringBuilder object to create the file path for the screenshot. It concatenates the image folder path, the current system time in milliseconds, and the image format.
Converts the StringBuilder object to a String and assigns it to the ‘fileName1’ variable.
Defines a Rectangle object that represents the area of the screen to be captured. It takes the starting coordinates (xStart, yStart) and the width and height calculated from (xEnd – xStart) and ( yEnd – yStart)
Uses the ‘createScreenCapture(captureRect)’ method of the Robot class to capture the screen within the specified Rectangle area. It returns a BufferedImage object representing the captured image.
Writes the captured image to the file specified by fileName1 using the write() method from the ImageIO class.
3. Click on Element by using the previous taking screenshot:
As we mentioned above sikuli methods, by using this method we will do multiple actions performed on elements.
Screen s = new Screen();
s.find(fileName1);
s.click(fileName1);
Limitations:
Manage a number of screenshots:
Managing a large number of screenshots can be a complex and time-consuming process. Locating a specific screenshot among many can become challenging. To simplify this process, a recommended solution is to establish a specific naming convention for the screenshots.
Two similar images are available on the webpage:
If there is more than one image available on the webpage, Sikuli cannot accurately categorize and distinguish a specific image. If it’s not a recognized image then it throws an exception.
Conclusion:
To overcome the challenges of locating elements in automation testing, especially within popup windows and MFC windows, we have successfully implemented Sikuli as a solution. So by adopting Sikuli, we can eliminate the need for traditional locators, leading to enhanced execution time and improved efficiency in our automation efforts. Sikuli’s visual recognition capabilities can help users swiftly identify and interact with GUI elements, enabling faster automation execution. Overall, Sikuli proves to be a valuable alternative in scenarios where traditional locators are insufficient or inaccessible.
An SDET with hands-on experience in the life science domain, including manual testing, functional testing, Jira, defect reporting, web application, and desktop application testing. I also have extensive experience in web and desktop automation using Selenium, WebDriver, WinAppDriver, Playwright, Cypress, Java, JavaScript, Cucumber, maven, POM, Xray, and building frameworks.