General SDET Interview Questions
The SDET interview questions below cover the scope of an SDET, which includes both the development and testing of software to enhance product quality.
1. What Is the Role of an SDET in a Development Team?
An SDET makes and manages automated test scripts to guarantee software applications meet quality and performance standards. They team up with developers to grasp the software structure and make automated tests mimicking real-world usage situations.
SDET participates in code reviews, design talks, and development and testing strategies. Their work ensures that software undergoes thorough testing and reaches desired quality levels before release.
2. How Do You Differentiate Between SDET and QA Engineer?
Here are the differences between SDET AND QA Engineers:
| SDET | QA Engineer |
|---|
| Works on both coding and testing. | Primarily focuses on testing. |
| Writes automated tests. | Run manual and automated tests to find bugs. |
| Strong programming skills and a good understanding of software design. | May not require as much coding or development knowledge. |
| Engages in the entire software development process. | Ensures the final product meets the required standards. |
3. What Are the Key Skills Required to Be an Effective SDET?
To be a good SDET, you need:
- Good programming languages, such as Java, Python, JavaScript, or C#.
- Good knowledge of automated testing tools like Selenium, JUnit, and TestNG.
- Understand software development and testing steps.
- Familiarity with CI/CD tools such as Jenkins and GitLab.
- Ability to write effective, reusable test code.
- Strong problem-solving and analytical skills.
- Good knowledge of version control systems like Git.
4. Can You Describe When You Identified a Critical Bug During the Testing Phase?
During the testing phase of the web application, I found a crucial bug with user authentication. This bug let unauthorized users get into accounts because of mishandled sessions. I made automated tests to mimic multiple logins at once, which helped me see exactly when the bug happened. I wrote down what I found, told the development team about it, and checked that the fix worked after they put it in.
5. How Do You Prioritize Test Cases in a Testing Cycle?
To ensure thorough testing coverage and effective risk management in a testing cycle, I prioritize test cases based on the following criteria:
- Critical business functionalities: Test cases covering core features that directly impact users.
- High-risk areas: Features with recent changes or complex code.
- Frequently used features: Functions that users interact with most often.
- Regulatory and compliance requirements: Tests ensuring legal and regulatory adherence.
- Past bug fixes: Areas with a history of issues to ensure no regression.
6. Explain the Difference Between Manual Testing and Automated Testing?
Here are the differences between manual and automated testing:
| Manual Testing | Automated Testing |
|---|
| Tests are executed manually by human testers. | Tests are executed using automated testing tools. |
| Requires human intervention for test execution and observation. | Minimizes human intervention once tests are automated. |
| Relatively slower due to manual execution. | Faster execution once automated, suitable for repetitive tests. |
| Limited scalability for complex or repetitive tests. | Handles complex scenarios and large test suites efficiently. |
| Quick setup; immediate start of testing. | Requires initial setup time for tool selection and scripting. |
| Requires ongoing manual effort for test maintenance. | Maintenance involves updating scripts and test cases. |
| Supports exploratory testing, creative and ad hoc testing. | Limited in exploratory testing capabilities. |
| Suitable for usability testing, ad hoc scenarios. | Ideal for regression testing, performance testing, and large-scale projects. |
If you are looking to get started in manual or automation testing, check out these manual testing interview questions and automation testing interview questions.
7. What Is Your Experience With Different Types of Testing (Unit, Integration, System, Acceptance)?
I have experience in unit, integration, system, and acceptance testing. I use tools like JUnit, TestNG, Selenium, and Cucumber to check software functionality and ensure quality.
- Unit testing: For unit testing, I primarily focus on making sure individual components or functions work correctly. My experience includes writing and maintaining unit tests using frameworks like JUnit for Java. It improved code quality and reliability by achieving high code coverage and ensuring that new features were thoroughly tested before integration.
If you want to start as a unit tester, check out this guide on unit testing interview questions.
- Integration testing: I have significant experience in integration testing, ensuring that parts of an application function together smoothly. I have used TestNG for integration tests, which has helped identify and resolve issues that arise from the interaction between different modules.
- System testing: During system testing, I confirm that the entire integrated application meets the defined requirements. I employ system testing Selenium for end-to-end testing to guarantee that all aspects of the application function together accurately and fulfill the requirements.
- Acceptance testing: I have worked on acceptance testing to ensure the software meets business needs and is ready for launch for the end user. I use Cucumber for behavior-driven development tests, which helps make sure the software works as expected and satisfies the end users' requirements.
Looking to start your career as a tester? Prepare from these top software testing questions.
8. How Do You Ensure That Your Test Cases Are Effective?
To ensure an effective test case, one should follow these best practices.
- Clear and concise: Test cases are well-defined with clear steps and expected outcomes.
- Traceability: Each test case is linked to specific requirements or user stories.
- Coverage: Ensure comprehensive coverage of functional and non-functional requirements.
- Review and update: Regularly review and update test cases based on new features and bug fixes.
- Peer review: Have test cases reviewed by peers to ensure accuracy and completeness.
9. What Strategies Do You Use to Handle Flaky Tests?
To effectively manage flaky tests, I employ several strategies:
- Stabilize test environment: Ensure consistent and stable test environments.
- Proper waits: Replace fixed sleeps with explicit waits for a specific condition. Avoid mixing implicit and explicit waits, because the Selenium documentation warns that the combination causes unpredictable wait times.
- Retry mechanism: Implement retry logic for transient issues.
- Isolation: Ensure tests are independent and do not affect each other.
- Root cause analysis: Identify and fix the underlying issues causing flakiness.
- Cloud-based testing: Leverage AI-driven test execution platforms such as TestMu AI. It comes with a Test Intelligence platform, offering custom flaky test detection and root cause analysis powered by AI. This helps address flaky tests.
10. How Do You Design a Test Automation Framework From Scratch?
- Start from the goals: The applications under test (web, mobile, API), the languages the team knows, and where the tests must run, which is usually a CI pipeline and a cloud grid.
- Layer the code: Tests, page objects or API clients, and a core layer for driver management, configuration, waits, and reporting, so a change in the application touches one place.
- Keep tests independent: Each test creates its own data and can run in parallel in any order.
- Externalize configuration: Environments, browsers, and credentials come from configuration files and secrets, never from the test code.
- Build in diagnostics: Logs, screenshots, videos, and network traces on failure, with a report that the whole team can read.
- Treat it as a product: Code review, static analysis, versioning, and documentation apply to test code as they do to production code.
11. What Is the Test Pyramid, and How Do You Apply It as an SDET?
The test pyramid is a model for balancing a test suite: many fast unit tests at the base, fewer integration and API tests in the middle, and a small number of end-to-end UI tests at the top. The higher a test sits, the slower, more expensive, and more fragile it is. An SDET applies the model by pushing each check to the lowest level that can prove it: business rules in unit tests, service behavior and contracts in API tests, and only the critical user journeys through the browser. A suite shaped like an ice cream cone, with mostly UI tests, is the usual cause of slow pipelines and flaky builds.
12. Can You Describe Your Experience With Continuous Integration and Continuous Deployment (CI/CD) Pipelines?
Experience establishing CI/CD pipelines with Jenkins and GitLab CI tools. I have set up automated builds, tests, and deployments to guarantee that code adjustments are consistently integrated, tested, and deployed.
This involves executing unit, integration, and end-to-end tests within the pipeline to give prompt feedback to developers and uphold top-notch software quality.
Key Takeaway: General SDET interview questions cover the SDET role of building and managing automated test scripts, how an SDET differs from a QA engineer by working on both coding and testing, key skills, test case prioritization, and manual versus automated testing.
Java-Related SDET Interview Questions
Here, we will cover Java-based SDET interview questions, including its core concepts, collections, data structures, concurrency, and multithreading.
13. Explain the Difference Between JDK, JRE, and JVM?
Below are the differences between JDK, JRE, and JVM:
| JDK (Java Development Kit) | JRE (Java Runtime Environment) | JVM (Java Virtual Machine) |
|---|
| Java Development Kit | Java Runtime Environment | Java Virtual Machine |
| Used for developing Java applications | Used for executing Java applications | Executes Java bytecode and provides a runtime environment |
| Includes JRE, compiler (javac), debugger (jdb), and other development tools | Includes JVM, libraries, and other components needed for running Java apps | Executes Java bytecode and manages memory, handles exceptions, etc. |
| Contains everything in JRE, plus development tools (compiler, debugger) | Contains libraries and JVM needed for running Java applications | Interprets Java bytecode and translates it into machine-specific code |
| Developers use JDK to write, compile, and debug Java code | End-users use JRE to run Java applications | Runs Java applications on different platforms |
| Required for Java application development | Required to run Java applications | Required to execute Java bytecode |
14. What Are the Main Principles of Object-Oriented Programming?
The main principles of Object-Oriented Programming are four: Encapsulation, Abstraction, Inheritance, and Polymorphism.
- Encapsulation: Bundling data (variables) and the methods that operate on that data into a single unit, called a class, and restricting direct access to the data through access modifiers.
- Abstraction: Hiding the implementation details and showing only the necessary features of an object, through abstract classes and interfaces.
- Inheritance: The mechanism through which one class inherits the fields and methods of another class.
- Polymorphism: The ability of an object to take many forms. The same method call performs different actions depending on the object it is invoked on.
15. Can You Explain the Concept of Inheritance and How It Is Implemented in Java?
This is a popular SDET interview question. Inheritance is a feature that allows one class (subclass/child class) to inherit the fields and methods of another class (superclass/parent class). In Java, it is implemented using the extends keyword.
Implementation in Java:
In Java, inheritance is implemented using the extends keyword. Here's how it works:
// Superclass: Product
class Product {
private String name;
private double price;
public Product(String name, double price) {
this.name = name;
this.price = price;
}
public void displayDetails() {
System.out.println("Name: " + name);
System.out.println("Price: $" + price);
}
}
// Subclass: ElectronicProduct inherits from Product
class ElectronicProduct extends Product {
private String brand;
public ElectronicProduct(String name, double price, String brand) {
super(name, price); // Call to superclass constructor
this.brand = brand;
}
public void displayBrand() {
System.out.println("Brand: " + brand);
}
}
// Subclass: ClothingProduct inherits from Product
class ClothingProduct extends Product {
private String size;
public ClothingProduct(String name, double price, String size) {
super(name, price); // Call to superclass constructor
this.size = size;
}
public void displaySize() {
System.out.println("Size: " + size);
}
}
public class EcommerceInheritanceExample {
public static void main(String[] args) {
ElectronicProduct laptop = new ElectronicProduct("Laptop", 1200.00, "Dell");
ClothingProduct shirt = new ClothingProduct("T-shirt", 29.99, "M");
laptop.displayDetails(); // Inherited method from Product
laptop.displayBrand(); // Method specific to ElectronicProduct
System.out.println(); // Blank line for separation
shirt.displayDetails(); // Inherited method from Product
shirt.displaySize(); // Method specific to ClothingProduct
}
}
This Java example demonstrates inheritance in an eCommerce context. The Product superclass defines common attributes (name, price) and a method (displayDetails()).
Subclasses like ElectronicProduct (with brand attribute and displayBrand() method) and ClothingProduct (with size attribute and displaySize() method) extend Product, inheriting its functionality while adding specific product details.
The main method creates instances of these subclasses (laptop and shirt), initializes their attributes, and showcases method invocations to display product details and specific attributes.
16. What Is Polymorphism, and How Does Java Support It?
Polymorphism allows objects to be treated as instances of their parent class rather than their actual class. Java supports polymorphism through method overriding and method overloading.
- Method Overriding: Method overriding occurs when a subclass provides a specific version of a method already in its superclass. The method to execute is determined at runtime based on the object type.
// Superclass
class Employee {
public void introduce() {
System.out.println("I am an employee.");
}
}
// Subclass overriding introduce()
class Developer extends Employee {
@Override
public void introduce() {
System.out.println("I am a developer.");
}
}
public class MethodOverridingExample {
public static void main(String[] args) {
Employee emp = new Developer(); // Employee reference but Developer object
emp.introduce(); // Output: "I am a developer."
}
}
- Method overloading: Method overloading permits applying more than one technique with the same name within the same class but with one-of-a-kind parameters. The technique that runs is completed at compile time primarily based on the range and kind of parameters.
class PaymentProcessor {
// Method overloading
public void processPayment(String paymentType) {
System.out.println("Processing payment using " + paymentType);
}
public void processPayment(String paymentType, double amount) {
System.out.println("Processing payment of $" + amount + " using " + paymentType);
}
}
public class MethodOverloadingExample {
public static void main(String[] args) {
PaymentProcessor processor = new PaymentProcessor();
processor.processPayment("Credit Card"); // Output: "Processing payment using Credit Card"
processor.processPayment("Bank Transfer", 500.00); // Output: "Processing payment of $500.0 using Bank Transfer"
}
}
17. Describe Exception Handling in Java. How Do You Use Try-Catch Blocks?
Exception handling in Java is used to handle runtime errors and maintain the normal flow of the application. It uses below keywords:
- try: Block of code where exceptions might occur.
- catch: Block of code that handles the exception.
- finally: Block of code that executes regardless of whether an exception is thrown.
- throw: Used to explicitly throw an exception.
public class BankingApplication {
public static void main(String[] args) {
try {
double balance = withdraw(1000.00, 1500.00);
System.out.println("Withdrawal successful. Remaining balance: " + balance);
} catch (InsufficientFundsException e) {
System.err.println("Transaction failed: " + e.getMessage());
} finally {
System.out.println("Transaction completed.");
}
}
public static double withdraw(double balance, double amount) throws InsufficientFundsException {
if (amount > balance) {
throw new InsufficientFundsException("Insufficient funds. Available balance: " + balance);
}
return balance - amount;
}
}
class InsufficientFundsException extends Exception {
public InsufficientFundsException(String message) {
super(message);
}
}
Exception handling in the BankingApplication ensures smooth transaction flows. The withdraw() method attempts a withdrawal, throwing an InsufficientFundsException if funds are inadequate.
The main() method catches this exception, prints an error message, and ensures transaction completion in the finally block.
18. What Is the Difference Between ArrayList and LinkedList?
This is one of the commonly asked SDET interview questions. Below are the differences between ArrayList and LinkedList:
| ArrayList | LinkedList |
|---|
| Uses a resizable array to store elements. | Uses a doubly linked list to store elements. |
| Provides fast access via index (O(1) time complexity). | Access is slower compared to ArrayList (O(n) time complexity). |
| Slower for insertion and deletion operations (O(n) complexity). | Faster for insertion and deletion operations (O(1) complexity). |
| More memory overhead due to unused array slots. | Less memory overhead per element. |
| Fast iteration using a for-each loop or traditional for loop. | Iteration can be slower compared to ArrayList. |
| Efficient for random access and search operations. | Inefficient for random access and search operations. |
| Suitable when frequent access and traversal are required. | Suitable when frequent insertion and deletion are required. |
| Better performance for scenarios involving random access. | Better performance for scenarios involving frequent modifications. |
| Data retrieval applications, where elements are accessed by index | Implementing queues, where elements are frequently added or removed |
19. Explain the Concept of a Map in Java. What Are the Different Types of Maps Available?
A Map is a collection that maps keys to values. Each key can map to at most one value.
Types of maps:
- HashMap: Stores keys and values based on their hashcode. It allows null keys and values and does not maintain order.
- LinkedHashMap: Extends HashMap and maintains insertion order using a doubly-linked list.
- TreeMap: Implements NavigableMap interface using a Red-Black tree. Maintains keys in sorted order.
- Hashtable: Synchronized version of HashMap. Does not allow null keys or values.
20. How Do You Synchronize a Collection in Java?
To synchronize a collection in Java, you can use Collections.synchronized methods to obtain synchronized versions of collections such as List, Map, Set, etc.
Example:
List<String> synchronizedList = Collections.synchronizedList(new ArrayList<>());
Map<String, String> synchronizedMap = Collections.synchronizedMap(new HashMap<>());
Set<String> synchronizedSet = Collections.synchronizedSet(new HashSet<>());
These synchronized collections provide thread-safe operations on the underlying collection, ensuring that modifications are properly synchronized across threads.
21. What Is a Comparator, and How Is It Different From Comparable?
Comparable: Interface defines the natural ordering of objects in a class. It has a compareTo method.
class Student implements Comparable<Student> {
int rollNo;
String name;
Student(int rollNo, String name) {
this.rollNo = rollNo;
this.name = name;
}
@Override
public int compareTo(Student s) {
return this.rollNo - s.rollNo;
}
}
Comparator: Interface used to define an external ordering of objects. It has a compare method.
import java.util.Comparator;
class NameComparator implements Comparator<Student> {
@Override
public int compare(Student s1, Student s2) {
return s1.name.compareTo(s2.name);
}
}
22. Can You Explain How a HashMap Works?
A HashMap stores pairs of keys and values. It uses a hash function to calculate an index (hashcode) in an array of buckets or slots where the needed value is stored.
- Hashing: Hashing involves changing the key into a hashcode.
- Buckets: Array of linked lists (or trees in case of high collisions).
- Put operation: Computes the bucket index from the hashcode of the key, adds the key-value pair to the corresponding bucket.
- Get operation: Computes the bucket index from the hashcode of the key, searches the bucket for the key, and returns the value.
Example:
import java.util.HashMap;
import java.util.Map;
public class HashMapExample {
public static void main(String[] args) {
// Create a HashMap
Map<String, Integer> hashMap = new HashMap<>();
// Add key-value pairs
hashMap.put("John", 25);
hashMap.put("Jane", 30);
hashMap.put("Doe", 40);
// Retrieve values
System.out.println("Age of John: " + hashMap.get("John")); // Output: Age of John: 25
}
}
In this example, we use a HashMap to store age information (Integer) linked to names (String). To add entries, we use the put() method, and to get values based on keys, we use the get() method.
23. What Is the Difference Between a Process and a Thread?
This is one of the commonly asked SDET interview questions. Here is the difference between a process and a thread:
- Process: Independent program execution with its own memory space. Processes are heavyweight and have a higher overhead.
- Thread: Subset of a process that shares the process's memory and resources. Threads are lightweight and have lower overhead.
24. How Do You Create a Thread in Java?
Threads in Java can be created by extending the Thread class or by implementing the Runnable interface.
- Extending Thread class:
class MyThread extends Thread {
@Override
public void run() {
System.out.println("Thread is running");
}
}
public class Main {
public static void main(String[] args) {
MyThread t1 = new MyThread();
t1.start();
}
}
- Implementing Runnable interface:
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("Thread is running");
}
}
public class Main {
public static void main(String[] args) {
Thread t1 = new Thread(new MyRunnable());
t1.start();
}
}
In both cases, the run() method is overridden to define the code that executes when the thread starts. The start() method is called on the Thread object to begin execution, and calling run() directly would execute the code on the current thread instead.
25. Explain the Concept of Synchronization in Java.
Synchronization in Java controls the access of multiple threads to shared resources. It prevents more than one thread from executing a critical block of code at the same time, which would otherwise lead to inconsistent data.
- Synchronized method: Locks the entire method for a particular object instance. Only one thread can execute the synchronized method for that object at a time.
public synchronized void synchronizedMethod() {
// Synchronized code block
}
- Synchronized block: Allows more granular control over synchronization by locking on a specific object instance or class.
public void method() {
synchronized (this) {
// Synchronized code block
}
}
26. What Are the Differences Between the Synchronized Block and the Synchronized Method?
Below are the differences between synchronized block and synchronized method:
| Synchronized Block | Synchronized Method |
|---|
| Applies synchronization to a specific block of code. | Applies synchronization to the entire method. |
| Provides flexibility to synchronize different objects. | Restricts synchronization to the entire method. |
| Fine-grained control over synchronized sections. | Coarse-grained synchronization for the entire method. |
| Lock is released immediately after the synchronized block. | Lock is released after the entire synchronized method is completed. |
| May have better performance due to finer control over locking. | May have performance implications if used on entire methods. |
27. Describe the Executor Framework in Java.
The Executor framework provides a higher-level replacement for working with threads and managing a pool of worker threads.
- Executor: Interface providing a single execute method to launch tasks.
- ExecutorService: Sub-interface adding lifecycle management methods for terminating and shutting down the executor.
- ThreadPoolExecutor: Implementation of ExecutorService that uses a pool of threads to execute tasks.
Example:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ExecutorExample {
public static void main(String[] args) {
// Create a fixed-size thread pool with 10 threads
ExecutorService executor = Executors.newFixedThreadPool(10);
// Execute tasks asynchronously
executor.submit(() -> {
// Task to execute
System.out.println("Task executed by thread: " + Thread.currentThread().getName());
});
// Shutdown the executor
executor.shutdown();
}
}
In this example, Executors.newFixedThreadPool(10) creates a thread pool with ten threads. The submit() method is used to submit tasks (Runnable objects) for execution. Finally, shutdown() is called on the ExecutorService to shut down the executor after completing all tasks.
Key Takeaway: Java-related SDET interview questions cover the difference between JDK, JRE, and JVM, inheritance, exception handling with try-catch blocks, Map implementations such as HashMap, Comparable versus Comparator, processes versus threads, and thread pools.
Coding and Algorithm-Related SDET Interview Questions
Now, let’s look at SDET interview questions around coding and algorithms.
28. Write a Java Program to Find the Largest Element in an Array.
Below is a Java program to find the largest element in an array.
public class LargestElement {
public static void main(String[] args) {
int[] array = {1, 3, 4, 2, 5};
int max = array[0];
for (int i = 1; i < array.length; i++) {
if (array[i] > max) {
max = array[i];
}
}
System.out.println("Largest element: " + max);
}
}
Output:
Largest element: 5
The program finds the largest number in an array. It takes the first element as the initial maximum (max), iterates through every element, and updates max each time a larger number is found, until all elements are checked.
29. How Would You Reverse a String in Java?
Below is a Java program to reverse a string in Java.
public class ReverseString {
public static void main(String[] args) {
String str = "lambdatest";
StringBuilder reversed = new StringBuilder(str);
reversed.reverse();
System.out.println("Reversed string: " + reversed.toString());
}
}
Output:
Reversed string: tsetadbmal
The above program reverses a string using StringBuilder. It starts by initializing a StringBuilder with the input string (str). Then, it uses the reverse() method on StringBuilder to reverse the characters.
Finally, it converts StringBuilder back to a string using toString() and prints the reversed string. This approach leverages StringBuilder's efficient handling of string manipulations, ensuring quick reversal of the input string.
30. Write a Function to Check if a Given String Is a Palindrome
Below is a Java program that writes a function to check if a given string is a palindrome.
public class PalindromeCheck {
public static void main(String[] args) {
String str = "madam";
if (isPalindrome(str)) {
System.out.println(str + " is a palindrome");
} else {
System.out.println(str + " is not a palindrome");
}
}
public static boolean isPalindrome(String str) {
int left = 0;
int right = str.length() - 1;
while (left < right) {
if (str.charAt(left) != str.charAt(right)) {
return false;
}
left++;
right--;
}
return true;
}
}
Output:
madam is a palindrome
The isPalindrome() function checks if a string reads the same forwards and backward. It uses two pointers, one starting at the beginning and one at the end, moving towards the center while comparing characters.
If characters at any point differ, it returns false. If all characters match, it returns true.
31. How Do You Remove Duplicates From an Array in Java?
Below is a Java program that removes duplicates from an array.
import java.util.*;
public class RemoveDuplicates {
public static void main(String[] args) {
int[] array = {1, 2, 2, 3, 4, 4, 5};
int[] result = removeDuplicates(array);
System.out.println("Array with duplicates removed: " + Arrays.toString(result));
}
public static int[] removeDuplicates(int[] array) {
Arrays.sort(array); // Sort the array to bring duplicates together
int[] uniqueArray = new int[array.length];
int j = 0;
for (int i = 0; i < array.length - 1; i++) {
if (array[i] != array[i + 1]) {
uniqueArray[j++] = array[i];
}
}
uniqueArray[j++] = array[array.length - 1]; // Add last element
return Arrays.copyOfRange(uniqueArray, 0, j); // Return array with unique elements
}
}
Output:
Array with duplicates removed: [1, 2, 3, 4, 5]
The removeDuplicates() function removes duplicates from an integer array. It sorts the array, then iterates through it, skipping duplicates and storing unique elements in uniqueArray. Finally, it returns a copy of uniqueArray without trailing zeros, ensuring only distinct values are included.
32. Write a Java Program to Find the Intersection of Two Arrays.
Below is a Java program that can help you find the intersection of two arrays.
import java.util.*;
public class IntersectionOfArrays {
public static void main(String[] args) {
int[] array1 = {1, 2, 2, 3, 4};
int[] array2 = {2, 2, 3, 5};
int[] intersection = findIntersection(array1, array2);
System.out.println("Intersection of arrays: " + Arrays.toString(intersection));
}
public static int[] findIntersection(int[] array1, int[] array2) {
Set<Integer> set1 = new HashSet<>();
for (int num : array1) {
set1.add(num);
}
Set<Integer> intersectionSet = new HashSet<>();
for (int num : array2) {
if (set1.contains(num)) {
intersectionSet.add(num);
}
}
int[] intersection = new int[intersectionSet.size()];
int index = 0;
for (int num : intersectionSet) {
intersection[index++] = num;
}
return intersection;
}
}
Output:
Intersection of arrays: [2, 3]
The findIntersection() function identifies common elements between two arrays. It stores unique elements of the first array in a HashSet, then iterates through the second array, adding elements found in the HashSet to another HashSet called intersectionSet.
Finally, it converts intersectionSet to an array and returns it, ensuring efficient capture of unique common elements.
33. How Do You Detect a Cycle in a Linked List?
Below is a Java program that detects a cycle in a linked list.
class ListNode {
int val;
ListNode next;
ListNode(int val) { this.val = val; this.next = null; }
}
public class DetectCycle {
public static void main(String[] args) {
ListNode head = new ListNode(3);
head.next = new ListNode(2);
head.next.next = new ListNode(0);
head.next.next.next = new ListNode(-4);
head.next.next.next.next = head.next; // Create a cycle
boolean hasCycle = hasCycle(head);
System.out.println("Linked list has cycle: " + hasCycle);
}
public static boolean hasCycle(ListNode head) {
if (head == null || head.next == null) {
return false;
}
ListNode slow = head;
ListNode fast = head.next;
while (slow != fast) {
if (fast == null || fast.next == null) {
return false;
}
slow = slow.next;
fast = fast.next.next;
}
return true;
}
}
Output:
Linked list has cycle: true
The hasCycle() function detects cycles in a linked list using two pointers, slow and fast. Slow starts at the head, and fast starts at the head.next. They move through the list until they meet (indicating a cycle) or quickly reach the end (indicating no cycle).
If fast or fast.next becomes null, there's no cycle, and the function returns false. This method is efficient with constant space and linear time complexity.
34. Write a Function to Reverse a Linked List.
Below is a Java program that reverses a linked list.
class ListNode {
int val;
ListNode next;
ListNode(int val) { this.val = val; this.next = null; }
}
public class ReverseLinkedList {
public static void main(String[] args) {
ListNode head = new ListNode(1);
head.next = new ListNode(2);
head.next.next = new ListNode(3);
head.next.next.next = new ListNode(4);
ListNode reversed = reverseList(head);
printList(reversed);
}
public static ListNode reverseList(ListNode head) {
ListNode prev = null;
ListNode current = head;
while (current != null) {
ListNode next = current.next; // Store next node
current.next = prev; // Reverse current node's pointer
prev = current; // Move pointers one position ahead
current = next; // Move pointers one position ahead
}
return prev; // Previous is now the head of reversed List
}
public static void printList(ListNode head) {
ListNode current = head;
while (current != null) {
System.out.print(current.val + " ");
current = current.next;
}
System.out.println();
}
}
Output:
4 3 2 1
The reverseList() function reverses a linked list directly where it's stored. It manages this using three pointers: prev, current, and next. As it goes through the list, it modifies each node's next pointer to point to the previous node instead of the next one. This operation is repeated until it reaches the end of the list (current becomes null).
Ultimately, it returns prev, which now serves as the head of the newly reversed list. This approach ensures the linked list is reversed efficiently and in place without requiring additional space beyond a few pointers.
35. How Would You Find the Middle Element of a Linked List?
Below is a Java program to find the middle element of a linked list.
class ListNode {
int val;
ListNode next;
ListNode(int val) { this.val = val; this.next = null; }
}
public class MiddleOfLinkedList {
public static void main(String[] args) {
ListNode head = new ListNode(1);
head.next = new ListNode(2);
head.next.next = new ListNode(3);
head.next.next.next = new ListNode(4);
head.next.next.next.next = new ListNode(5);
ListNode middle = findMiddle(head);
System.out.println("Middle element of linked list: " + middle.val);
}
public static ListNode findMiddle(ListNode head) {
ListNode slow = head;
ListNode fast = head;
while (fast != null && fast.next != null) {
slow = slow.next; // Move slow pointer by 1
fast = fast.next.next; // Move fast pointer by 2
}
return slow; // Slow pointer is at the middle node
}
}
Output:
Middle element of linked list: 3
The findMiddle() function determines the middle element of a linked list by employing the "slow and fast pointer" technique. Initially, both slow and fast pointers are set to the head of the list.
As the while loop progresses, slow moves one step forward while fast moves two steps forward. This continues until fast either reaches the end of the list or moves beyond it. When fast reaches the end, slow will be positioned at the middle element of the linked list.
36. Write a Java Program to Merge Two Sorted Linked Lists.
Below is a Java program to merge two sorted linked lists.
class ListNode {
int val;
ListNode next;
ListNode(int val) { this.val = val; this.next = null; }
}
public class MergeSortedLinkedLists {
public static void main(String[] args) {
ListNode l1 = new ListNode(1);
l1.next = new ListNode(3);
l1.next.next = new ListNode(5);
ListNode l2 = new ListNode(2);
l2.next = new ListNode(4);
l2.next.next = new ListNode(6);
ListNode merged = mergeTwoLists(l1, l2);
printList(merged);
}
public static ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode dummy = new ListNode(0);
ListNode current = dummy;
while (l1 != null && l2 != null) {
if (l1.val < l2.val) {
current.next = l1;
l1 = l1.next;
} else {
current.next = l2;
l2 = l2.next;
}
current = current.next;
}
current.next = (l1 != null) ? l1 : l2;
return dummy.next;
}
public static void printList(ListNode head) {
ListNode current = head;
while (current != null) {
System.out.print(current.val + " ");
current = current.next;
}
System.out.println();
}
}
Output:
1 2 3 4 5 6
The mergeTwoLists() function combines two sorted linked lists into one sorted linked list. It employs a dummy node to facilitate the merging process and ensure the resulting list starts correctly.
The function iterates through input lists (l1 and l2), comparing nodes at each step and linking them in ascending order to the current node. Any remaining nodes from l1 or l2 are appended to current.next.
Finally, the function returns dummy.next, which points to the head of the merged sorted linked list.
37. How Would You Remove the Nth Node From the End of a Linked List?
Below is a Java program that removes the Nth node from the end of a linked list.
class ListNode {
int val;
ListNode next;
ListNode(int val) { this.val = val; this.next = null; }
}
public class RemoveNthFromEnd {
public static void main(String[] args) {
ListNode head = new ListNode(1);
head.next = new ListNode(2);
head.next.next = new ListNode(3);
head.next.next.next = new ListNode(4);
head.next.next.next.next = new ListNode(5);
ListNode updated = removeNthFromEnd(head, 2);
printList(updated);
}
public static ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode first = dummy;
ListNode second = dummy;
// Move second pointer n steps ahead
for (int i = 1; i <= n + 1; i++) {
second = second.next;
}
// Move both pointers until second is at the end
while (second != null) {
first = first.next;
second = second.next;
}
// Remove the nth node from the end
first.next = first.next.next;
return dummy.next; // Return head of updated list
}
public static void printList(ListNode head) {
ListNode current = head;
while (current != null) {
System.out.print(current.val + " ");
current = current.next;
}
System.out.println();
}
}
Output:
1 2 3 5
The removeNthFromEnd() function removes the Nth node from the end of a linked list using two pointers, first and second, starting from a dummy node. The second is advanced n + 1 steps ahead, then both move until the second reaches the end.
First adjusts to skip the Nth node, effectively removing it. Finally, it returns dummy.next, pointing to the updated list head.
38. Explain the Difference Between a Binary Tree and a Binary Search Tree.
- Binary Tree: A tree data structure in which every node has at most two children.
- Binary Search Tree (BST): A binary tree in which the left subtree of every node contains only values smaller than the node, and the right subtree contains only values larger than the node.
39. Write a Function to Perform an In-Order Traversal of a Binary Tree.
Below is a Java program that performs an in-order traversal of a binary tree.
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int val) { this.val = val; this.left = null; this.right = null; }
}
public class InOrderTraversal {
public static void main(String[] args) {
TreeNode root = new TreeNode(1);
root.left = new TreeNode(2);
root.right = new TreeNode(3);
root.left.left = new TreeNode(4);
root.left.right = new TreeNode(5);
System.out.println("In-order traversal:");
inOrder(root);
}
public static void inOrder(TreeNode root) {
if (root != null) {
inOrder(root.left); // Visit left subtree
System.out.print(root.val + " "); // Visit root
inOrder(root.right); // Visit right subtree
}
}
}
Output:
In-order traversal:
4 2 5 1 3
The inOrder() function performs an in-order traversal of a binary tree, which visits the nodes in a fixed sequence: the left subtree, the current node (root), and then the right subtree. The traversal is recursive, which means the function calls itself for every subtree until all nodes are visited. When applied to a binary search tree (BST), the in-order traversal prints the node values in ascending order.
This traversal technique is recursive, which means it calls itself to traverse every subtree until all nodes are visited. When applied to a binary search tree (BST), the in-order traversal prints node values in ascending sorted order.
This order makes the traversal useful for tasks such as retrieving the elements of a BST in sorted order.
40. How Do You Check if a Binary Tree Is Balanced?
Shown below is a Java program to check if a binary tree is balanced.
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int val) { this.val = val; this.left = null; this.right = null; }
}
public class BalancedBinaryTree {
public static void main(String[] args) {
TreeNode root = new TreeNode(1);
root.left = new TreeNode(2);
root.right = new TreeNode(3);
root.left.left = new TreeNode(4);
root.left.right = new TreeNode(5);
boolean balanced = isBalanced(root);
System.out.println("Is the binary tree balanced? " + balanced);
}
public static boolean isBalanced(TreeNode root) {
if (root == null) {
return true;
}
int leftHeight = height(root.left);
int rightHeight = height(root.right);
return Math.abs(leftHeight - rightHeight) <= 1 && isBalanced(root.left) && isBalanced(root.right);
}
public static int height(TreeNode node) {
if (node == null) {
return 0;
}
int leftHeight = height(node.left);
int rightHeight = height(node.right);
return Math.max(leftHeight, rightHeight) + 1;
}
}
Output:
Is the binary tree balanced? true
The isBalanced() function determines if a binary tree is balanced by checking that the height difference between the left and right subtrees is at most 1. It uses recursion to compute the height of the left and right subtrees of every node in the tree.
At each node, it verifies the balance condition using Math.abs(leftHeight - rightHeight) <= 1. The recursion checks this condition for every node from the root down to the leaves. A balanced binary tree matters because it keeps the height of the tree minimal, which keeps search and insert operations efficient.
41. Write a Java Program to Find the Shortest Path in a Graph.
This problem is generally solved using algorithms like Dijkstra's algorithm or Breadth-First Search (BFS).
import java.util.*;
public class ShortestPathInGraph {
public static void main(String[] args) {
Map<Integer, List<Integer>> graph = new HashMap<>();
graph.put(0, Arrays.asList(1, 2));
graph.put(1, Arrays.asList(2));
graph.put(2, Arrays.asList(0, 3));
graph.put(3, Arrays.asList());
int start = 2;
int end = 3;
int shortestPathLength = bfsShortestPath(graph, start, end);
System.out.println("Shortest path length from " + start + " to " + end + ": " + shortestPathLength);
}
public static int bfsShortestPath(Map<Integer, List<Integer>> graph, int start, int end) {
Queue<Integer> queue = new LinkedList<>();
Set<Integer> visited = new HashSet<>();
Map<Integer, Integer> distance = new HashMap<>();
queue.offer(start);
visited.add(start);
distance.put(start, 0);
while (!queue.isEmpty()) {
int node = queue.poll();
if (node == end) {
return distance.get(node);
}
for (int neighbor : graph.getOrDefault(node, Collections.emptyList())) {
if (!visited.contains(neighbor)) {
visited.add(neighbor);
queue.offer(neighbor);
distance.put(neighbor, distance.get(node) + 1);
}
}
}
return -1; // No path found
}
}
Output:
Shortest path length from 2 to 3: 1
The bfsShortestPath function employs BFS to discover the shortest path from the beginning to the end in a graph shown through an adjacency list (graph).
It sets up a queue to handle nodes, a set to record visited nodes, and a map to save distances from the beginning. The function then goes on to dequeue nodes in each iteration, enqueue unvisited neighbors, and adjust the distance accordingly.
Upon dequeuing the end node, the function provides the shortest path length as output.
42. How Do You Implement Depth-First Search (DFS) in Java?
Below is the Java program to implement depth-first search.
import java.util.*;
public class DepthFirstSearch {
public static void main(String[] args) {
// Create a graph represented by adjacency list
Map<Integer, List<Integer>> graph = new HashMap<>();
graph.put(0, Arrays.asList(1, 2));
graph.put(1, Arrays.asList(2));
graph.put(2, Arrays.asList(0, 3));
graph.put(3, Arrays.asList());
int start = 2; // Start DFS from node 2
System.out.println("DFS traversal starting from node " + start + ": ");
dfs(graph, start);
}
public static void dfs(Map<Integer, List<Integer>> graph, int start) {
Set<Integer> visited = new HashSet<>();
Stack<Integer> stack = new Stack<>();
stack.push(start);
visited.add(start);
while (!stack.isEmpty()) {
int node = stack.pop();
System.out.print(node + " ");
for (int neighbor : graph.getOrDefault(node, Collections.emptyList())) {
if (!visited.contains(neighbor)) {
visited.add(neighbor);
stack.push(neighbor);
}
}
}
System.out.println();
}
}
Output:
DFS traversal starting from node 2:
2 3 0 1
The dfs() function implements Depth-First Search (DFS) using a stack to facilitate the traversal of nodes in a graph or tree structure.
- Initialization: It initializes a stack to manage nodes for exploration in a Last In, First Out (LIFO) manner. A set (visited) keeps track of nodes that have already been visited to avoid processing them more than once.
- DFS Execution: Begins with the start node, pushing it onto the stack and marking it as visited in the set. While there are nodes in the stack, it pops the top node, processes it (prints or performs an action), and explores its neighbors. For each neighbor that hasn't been visited yet, it pushes the neighbor onto the stack and marks it as visited.
- Termination: The process continues until the stack is empty, indicating that all reachable nodes from the start node have been visited and processed.
43. Describe the QuickSort Algorithm and Its Time Complexity.
QuickSort is a divide-and-conquer sorting algorithm. It picks an element as a pivot and partitions the array around the pivot. Elements smaller than the pivot go to the left, and elements larger go to the right. It recursively sorts the sub-arrays.
Time Complexity:
- Best Case: O(n log n)
- Average Case: O(n log n)
- Worst Case: O(n^2)
Explanation:
- QuickSort selects a pivot, partitions the array, and recursively sorts the sub-arrays.
- Its efficiency depends on the choice of pivot and the partitioning strategy.
- Best and average cases achieve O(n log n) due to balanced partitions.
- The worst case (unbalanced partitions) occurs when the smallest or largest element is always chosen as the pivot, leading to O(n^2).
44. Write a Java Program to Implement Binary Search.
Below is the java program to implement binary search.
import java.util.*;
public class BinarySearch {
public static void main(String[] args) {
int[] array = {1, 3, 5, 7, 9, 11, 13, 15};
int target = 7;
int index = binarySearch(array, target);
if (index != -1) {
System.out.println("Element " + target + " found at index " + index);
} else {
System.out.println("Element " + target + " not found in the array");
}
}
public static int binarySearch(int[] array, int target) {
int left = 0;
int right = array.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (array[mid] == target) {
return mid; // Element found
} else if (array[mid] < target) {
left = mid + 1; // Search in the right half
} else {
right = mid - 1; // Search in the left half
}
}
return -1; // Element not found
}
}
Output:
Element 7 found at index 3
The binarySearch() function performs a binary search to locate a specific element in a sorted array. To begin, it sets up left and right pointers at the array's start and end, respectively.
Then, it calculates the middle index as "mid" and compares array[mid] to the target. If the target matches array[mid], it returns mid. If the target is greater than array[mid], it looks in the right half (updating left = mid + 1).
Conversely, for a smaller target, it searches the left half (adjusting right = mid - 1). This process repeats until left surpasses right, indicating the element is not found (then it returns -1).
45. What Is the Difference Between MergeSort and QuickSort?
Here are the differences between MergeSort and QuickSort:
| Feature | Merge Sort | Quick Sort |
|---|
| Stability | Stable sorting algorithm. | Unstable sorting algorithm. |
| Divide and Conquer Approach | Divides array into two halves recursively. | Divides array based on a pivot element. |
| Merge Process | Merges sorted subarrays into a single sorted array. | Sorting is done in place, with no explicit merge process. |
| Partitioning Mechanism | No pivot element. | Uses a pivot element to partition the array. |
| Average Time Complexity | O(n log n) | O(n log n) (average case) |
| Worst-case Time Complexity | O(n log n) | O(n^2) (rare, but possible with poor pivot selection) |
| Best-case Time Complexity | O(n log n) | O(n log n) |
| Space Complexity | O(n) auxiliary space for the merge process. | O(log n) auxiliary space for recursion stack. |
| Applications | Suitable for external sorting and stable sorting. | Often used due to average case efficiency, especially for large datasets. |
46. Explain the Concept of Bubble Sort and Its Drawbacks.
Bubble sort compares adjacent elements and swaps them if they are in the wrong order. It passes through the array multiple times, moving larger elements to the right and smaller ones to the left.
Drawbacks:
- Performance: Bubble Sort has an average and worst-case time complexity of O(n²), which makes it inefficient for large datasets.
- Stability: Although it maintains the order of equal elements, it's not ideal for sorting large amounts of data due to its slow speed.
- Adaptability: The basic version performs O(n²) comparisons even when the array is already sorted. The optimized version stops when a pass makes no swap, which gives a best case of O(n).
47. How Do You Find the Kth Largest Element in an Unsorted Array?
Below is a Java program to find the Kth Largest Element in an Unsorted Array
import java.util.*;
public class KthLargestElement {
public static void main(String[] args) {
int[] array = {3, 2, 1, 5, 6, 4};
int k = 2;
int kthLargest = findKthLargest(array, k);
System.out.println("The " + k + "-th largest element in the array is: " + kthLargest);
}
public static int findKthLargest(int[] nums, int k) {
PriorityQueue<Integer> minHeap = new PriorityQueue<>();
for (int num : nums) {
minHeap.offer(num);
if (minHeap.size() > k) {
minHeap.poll(); // Remove the smallest element if heap size exceeds k
}
}
return minHeap.peek(); // The root of the heap is the k-th largest element
}
}
Output:
The 2-th largest element in the array is: 5
The function findKthLargest() efficiently uses a min-heap to identify the kth largest item in an array that is not organized. It starts by setting up a minHeap and then includes items from nums.
Whenever the heap's size surpasses k, it eliminates the smallest item (minHeap.poll()). Ultimately, it gives back the main element of the heap (minHeap.peek()), which represents the kth largest item.
Key Takeaway: Coding and algorithm SDET interview questions ask for Java programs that find the largest array element, remove duplicates, reverse a linked list, remove the Nth node from the end, check whether a binary tree is balanced, and explain QuickSort.
AI and Agentic SDET Interview Questions
AI changed the SDET role in two directions: AI agents now write and maintain part of the test code, and the products under test increasingly contain AI features themselves. Interviews in 2026 cover both.
48. How Are AI Agents Changing the Work of an SDET?
- Test authoring: Agents generate test cases from requirements, write automation code from a plain-language description, and explore an application to propose new scenarios.
- Maintenance: Self-healing locators and agents that repair a broken test after a UI change reduce the time spent on upkeep.
- Triage: Failure logs are classified automatically into product bugs, test bugs, and environment issues, and flaky tests are detected from run history.
- The shift for the SDET: Less typing of scripts, and more work on test strategy, the framework and guardrails the agents operate in, test data, and the review of what the agents produce.
The accountability does not move: the SDET still decides what must be tested and whether the evidence is good enough to release.
49. How Do You Review Test Code That an AI Assistant or Agent Generated?
- Weak assertions: Tests that only check that no exception was thrown, or that assert the value the code currently returns instead of the value the requirement demands.
- Invented APIs: Methods, locators, or endpoints that do not exist in the framework or the application.
- Brittle locators and fixed sleeps: Absolute XPath expressions and Thread.sleep() calls in place of stable locators and explicit waits.
- Hidden dependencies: Tests that rely on execution order or on shared data.
- Proof of value: Run the test, then break the feature on purpose, and confirm that the test fails.
50. How Do You Test an Application That Uses an LLM or an AI Agent?
- Non-deterministic output: Exact-match assertions do not work, so the tests check properties of the answer: its format, the required facts, the forbidden content, and its similarity to a reference answer.
- Evaluation datasets: A versioned set of prompts with expected behavior runs on every change to the prompt, the model, or the retrieval data, and the scores are compared with a baseline.
- Model-graded checks: A second model scores qualities such as relevance or tone, and people review a sample of those scores to keep the grader honest.
- Agent behavior: The tests assert which tools the agent called, with which arguments, and that it stopped within its step and cost limits.
- Safety tests: Prompt injection, data leakage, and harmful request scenarios are part of the regression suite.
- Non-functional limits: Latency, cost per request, and behavior when the model provider is slow or unavailable.
Key Takeaway: AI agents take over part of test authoring, maintenance, and triage, so the SDET focuses on strategy, guardrails, and review, generated tests are checked for weak assertions, invented APIs, and brittle waits, and AI features are tested with evaluation datasets, property-based assertions, tool-call checks, and safety scenarios.
Subscribe to the TestMu AI YouTube Channel and stay updated with the latest video tutorials on automation testing.
Conclusion
Mastering key Java concepts like JDK, JRE, JVM, OOP principles, and exception handling is essential for SDETs. These skills enable the creation of scalable, reliable test automation frameworks and contribute to Agile teams, ensuring high-quality software and continuous improvement in testing methodologies.