Table of Contents
2. Core Java Programming for Automation
It is one of the most popular programming languages for automation due to its versatility, scalability, and support for automation tools like Selenium. In this blog, we will explore core Java concepts that are essential for anyone looking to get into automation testing or development. From setting up your environment to understanding key Object-Oriented Programming (OOP) principles, this guide will provide a solid foundation in Java programming.
2.1 Introduction to Java
It is a high-level, object-oriented programming language developed by Sun Microsystems (now owned by Oracle) in 1995. Known for its “write once, run anywhere” capability, It is enables developers to create platform-independent applications that can run on various devices, from servers to smartphones.
It’s simplicity, reliability, and powerful libraries make it ideal for automation testing. Most automation frameworks, such as Selenium, are built in Java, and learning the language opens up a broad range of automation opportunities.
2.2 Setting Up the Java Environment (JDK, IDEs)
To start coding in Java, you need to set up the JDK and an Integrated Development Environment (IDE).
- JDK (Java Development Kit): The JDK includes the Java Runtime Environment (JRE), compiler, and other tools required to develop Java applications.
- Download and install the JDK from Oracle’s official website.
- IDEs (Integrated Development Environments): Tools like Eclipse or IntelliJ IDEA offer features such as code suggestions, syntax highlighting, and debugging tools that make Java development easier.
Once installed, configure the environment variables and test the setup by writing a simple “Hello, World!” program in Java.
2.3 Java Basics: Data Types, Variables, Operators
Understanding Java’s core elements is crucial for writing efficient code for automation.
- Data Types: It supports primitive data types like int, float, double, char, and boolean. Additionally, it has reference types such as String and Array.
- Variables: Variables are used to store data. You declare a variable by specifying its data type followed by the variable name: int age = 25;
- Operators: Operators are allowed to perform operations on variables and data. They include arithmetic operators (+, -, *, /), relational operators (==, !=, >, <), and logical operators (&&, ||).
2.4 Control Structures: Conditional Statements, Loops
Control structures manage the flow of a program based on conditions or iterations.
- Conditional Statements:
- if, else if, and else statements control the flow of execution based on a boolean condition.
- switch statement is useful when you need to test a variable against multiple values.
- Loops:
- For Loop: Executes a block of code a specific number of times: for (int i = 0; i < 5; i++) { //code }.
- While Loop: Repeats a block of code as long as a condition is true.
- Do-While Loop: Similar to a while loop but ensures that the block of code is executed at least once.
2.5 Object-Oriented Programming (OOP) Concepts
Java is an object-oriented programming language that emphasizes creating objects that represent real-world entities. OOP principles are fundamental in Java automation frameworks.
2.5.1 Classes and Objects
A class is a blueprint for objects. It defines properties and behaviours using variables and methods, respectively. An object is an instance of a class.
class Car {
String model;
void displayModel() {
System.out.println(model);
}
}
Car car = new Car();
car.model = "Toyota";
car.displayModel();
2.5.2 Inheritance
Inheritance allows one class (child class) to inherit the fields and methods of another class (parent class), promoting code reuse.
class Vehicle {
String fuel;
}
class Car extends Vehicle {
String model;
}
2.5.3 Polymorphism
Polymorphism means the ability to take many forms. Java supports method overloading and method overriding, which are two types of polymorphism.
- Method Overloading: Same method name but different parameter types.
- Method Overriding: Redefining a method in a child class that already exists in the parent class.
Method Overloading allows a class to have more than one method with the same name but different parameter lists. This is a form of compile-time polymorphism. Overloading is achieved by changing the number or type of parameters in the methods.
Key Points:
- Same Method Name: The methods must share the same name.
- Different Parameters: The methods must differ in the number, type, or order of their parameters.
- Return Type: Overloading does not depend on the return type alone; the parameters must be different.
public class Calculator {
// Method to add two integers
public int add(int a, int b) {
return a + b;
}
// Method to add three integers
public int add(int a, int b, int c) {
return a + b + c;
}
// Method to add two double values
public double add(double a, double b) {
return a + b;
}
}
Method Overriding occurs when a subclass provides a specific implementation of a method that is already defined in its superclass. This is a form of runtime polymorphism and allows a subclass to modify or extend the behavior of inherited methods.
Key Points:
- Same Method Signature: The overriding method must have the same name, return type, and parameter list as the method in the parent class.
- Access Modifier: The access level of the overriding method must be the same or more accessible than the method in the parent class.
@Override
Annotation: It’s a good practice to use the@Override
annotation to indicate that a method is being overridden.
class Animal {
// Method in the parent class
public void makeSound() {
System.out.println("Animal makes a sound");
}
}
class Dog extends Animal {
// Method overridden in the subclass
@Override
public void makeSound() {
System.out.println("Dog barks");
}
}
public class Test {
public static void main(String[] args) {
Animal myDog = new Dog();
myDog.makeSound(); // Output: Dog barks
}
}
2.5.4 Abstraction and Encapsulation
- Abstraction is the process of hiding the implementation details from the user and showing only essential features.
- Encapsulation involves bundling the data (variables) and the code (methods) into a single unit called a class.
class Employee {
private int id;
public void setId(int id) { this.id = id; }
public int getId() { return id; }
}
2.6 Exception Handling in Java
In Java, exceptions are events that disrupt the normal flow of the program. Exception handling ensures the program can handle runtime errors gracefully.
The primary keywords for exception handling are:
- try: Code that may throw an exception is placed inside a try block.
- catch: Used to handle the exception.
- finally: Execute regardless of whether an exception occurs or not.
- throw/throws: Used to manually throw exceptions.
try {
int result = 10 / 0;
} catch (ArithmeticException e) {
System.out.println("Cannot divide by zero!");
}
2.7 Collections Framework
The Collections Framework provides a set of classes and interfaces for storing and manipulating groups of data.
- List: An ordered collection that allows duplicates (e.g., ArrayList).
- Set: Unordered collection that doesn’t allow duplicates (e.g., HashSet).
- Map: Key-value pairs (e.g., HashMap).
List
A List is an ordered collection that allows duplicate elements. It maintains the insertion order, meaning that elements are stored in the order they were added, and you can access elements by their index.
Key Characteristics:
- Ordered: Elements are stored in the sequence they were inserted.
- Duplicates Allowed: You can store multiple instances of the same element.
- Indexed Access: You can access elements via their index.
Common Implementations:
- ArrayList: Provides a resizable array implementation. It’s the most commonly used List implementation due to its flexibility and ease of use.
- LinkedList: Implements a doubly-linked list. It supports efficient insertions and deletions but may be slower for random access compared to ArrayList.
import java.util.ArrayList;
import java.util.List;
public class Example {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
list.add("Apple"); // Duplicate element allowed
System.out.println(list); // Output: [Apple, Banana, Apple]
}
}
Set
A Set is an unordered collection that does not allow duplicate elements. It is used when you want to ensure that all elements are unique, and you don’t care about the order of the elements.
Key Characteristics:
- Unordered: The order of elements is not guaranteed to be the same as their insertion order.
- Duplicates Not Allowed: A Set automatically removes duplicate entries.
- Efficient Lookups: Sets generally provide fast operations for checking membership and removing duplicates.
Common Implementations:
- HashSet: Implements the Set interface with a hash table. It provides constant-time performance for basic operations like add, remove, and contains, assuming the hash function disperses elements properly.
- LinkedHashSet: Maintains a linked list of the entries in the set, which allows it to preserve the insertion order of elements.
- TreeSet: Implements the Set interface using a red-black tree. It sorts elements in natural order or according to a specified comparator.
import java.util.HashSet;
import java.util.Set;
public class Example {
public static void main(String[] args) {
Set<String> set = new HashSet<>();
set.add("Apple");
set.add("Banana");
set.add("Apple"); // Duplicate element will be ignored
System.out.println(set); // Output: [Apple, Banana]
}
}
Map
A Map is a collection of key-value pairs where each key is unique and maps to exactly one value. Maps are used when you need to associate unique keys with specific values.
Key Characteristics:
- Key-Value Pairs: Each entry consists of a key and a value.
- Unique Keys: Each key in the Map must be unique, but values can be duplicated.
- Unordered: The order of key-value pairs is not guaranteed.
Common Implementations:
- HashMap: Implements the Map interface using a hash table. It provides constant-time performance for basic operations (get and put) and does not guarantee any specific order of elements.
- LinkedHashMap: Maintains insertion order of elements, which means the order in which elements are inserted is preserved when iterating over the Map.
- TreeMap: Implements the Map interface using a red-black tree. It sorts the keys in natural order or according to a specified comparator.
import java.util.HashMap;
import java.util.Map;
public class Example {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
map.put("1", "Apple");
map.put("2", "Banana");
map.put("1", "Avocado"); // Key '1' will map to 'Avocado'
System.out.println(map); // Output: {1=Avocado, 2=Banana}
}
}
2.8 File Handling in Java
File handling in Java allows you to read and write data to files. Classes like FileReader, FileWriter, and BufferedReader are commonly used for this purpose.
FileWriter writer = new FileWriter("output.txt");
writer.write("Hello, World!");
writer.close();
2.9 Java Input/Output (I/O) Operations
Java’s I/O operations involve reading from and writing to streams of data, using classes like InputStream and OutputStream.
InputStream: The abstract base class for all byte input streams. It defines methods for reading bytes of data.
- FileInputStream: A concrete subclass of
InputStream
used for reading data from a file
import java.io.FileInputStream;
import java.io.IOException;
public class FileInputExample {
public static void main(String[] args) {
try (FileInputStream fis = new FileInputStream("example.txt")) {
int byteData;
while ((byteData = fis.read()) != -1) {
System.out.print((char) byteData);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
OutputStream: The abstract base class for all byte output streams. It defines methods for writing bytes of data.
- FileOutputStream: A concrete subclass of
OutputStream
used for writing data to a file.
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputExample {
public static void main(String[] args) {
try (FileOutputStream fos = new FileOutputStream("output.txt")) {
String data = "Hello, World!";
fos.write(data.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.10 Introduction to Java Streams and Lambda Expressions
Java Streams provide a functional approach to handling collections of objects. Lambda Expressions allow for writing concise code by enabling the use of anonymous methods.
List<Integer> numbers = Arrays.asList(1, 2, 3, 4);
numbers.stream().filter(n -> n % 2 == 0).forEach(System.out::println);
2.11 Introduction to Multi-threading in Java
Multi-threading allows concurrent execution of multiple threads to utilize CPU resources efficiently. Threads in Java can be created using the Thread class or implementing the Runnable interface.
class MyThread extends Thread {
public void run() {
System.out.println("Thread is running");
}
}
MyThread thread = new MyThread();
thread.start();
Conclusion
Core Java programming forms the foundation for automation testing. Understanding these concepts is essential for developing effective automated test scripts and frameworks, especially in tools like Selenium. Mastering Java will not only make you a proficient automation engineer but also open doors to a wide range of programming and testing opportunities.
To learn more about java and selenium Click here.