How To Use New Java Features In The Test Automation

Since Java 8 many new features have been introduced to implement Functional Programming, Which helps to reduce the gap between the business logic and the code. Functional programming is the subset of Declarative programming contrary to Procedural or Object-oriented programming.

In this article, we will see how we can use New Java features in the test automation framework to make it more elegant and readable. If you are not familiar with Java’s new features then please visit this article.

1)Java 8 ForEach Loop

The forEach loop was introduced in Java 8 to iterate over a collection and perform an action on each element. Since Java 8 we can pass Lambda expressions. Earlier we used to iterate over a list by using for loop or enhanced for loop. Look at the below example code:

1)Navigate to the Website.
2)Fetch all matching Web elements in a list.
3)Display the text.

 @Test
 public void TestHeaderLinks() throws InterruptedException {
    
  WebDriver driver= LocalDriverFactory.getDriver();
  driver.get("https://www.amazon.com/");
  List<WebElement>list=driver.findElements(By.xpath("//div[@id='nav-xshop']//a"));
  for(WebElement ele : list)
  {
  System.out.print(ele.getText());
  }

In the above code snippet, we can replace the for loop with a forEach loop. This expression starts with the name of the collection(list) and inside forEach, we have taken a single variable (ele) which is final and local and can not be used outside of this method call. (->) signifies lambda and we have assigned the action(ele.getText()) to the variable. Simple and looks more readable.

list.forEach(ele->System.out.print(ele.getText()));

forEach to loop a map: Suppose We have a map collection and we need to display all key values of this collection. How can we achieve this by using forEach?

Without ForEach:

Map<String, Integer> map = new HashMap<>();
for (Map.Entry<String, Integer> entry : map.entrySet()) {
    System.out.println("Key : " + entry.getKey() + ", Value : " +entry.getValue());
      }

With ForEach:

Map<String, Integer> map = new HashMap<>();
map.forEach((k, v) -> System.out.println("Key : " + k + ", Value : " + v));

2)Java 8 Streams API

Streams API was introduced in Java 8 by using which we can process, filter, or transform a set of collection data in any other required way. Streams API is part of Java. util package and has two mechanisms named the filter and map to process the data from the collections.

How Streams API Works: To Work with streams, first we add collection data into a stream and then perform required actions such as filtering or mapping on the stream and then store the processed data in some other collection or use it for some other purpose. So the original collection data will remain intact.

Let’s take a scenario where we need to filter out all the links that contain specific text.

 WebDriver driver= LocalDriverFactory.getDriver();
 driver.get("https://www.freshworks.com/");
 List<WebElement>el=driver.findElements(By.xpath("//a[contains(@href,'https://freshdesk.com/')]"));
 el.stream().filter(item->item.getText().contains("freshwork"))
 .collect(Collectors.toList()).forEach(item->System.out.println(item));

Let’s take another example, Where we need to perform certain tasks:

  • Navigate to a shopping website
  • Fetch all the links that contain anchor tags.
  • Remove empty links.
  • Remove the duplicates.
  • Display text that contains either “Shoes” or “Watches”

Without Using Stream API(Java 7)

 public void TestJava(){
      FrameworkConfig config= ConfigFactory.create(FrameworkConfig.class);

        WebDriver driver= LocalDriverFactory.getDriver();
        driver.get("https://www.myntra.com/");
        List<WebElement> el =driver.findElements(By.xpath("//a"));
      
        List<String> text=new ArrayList<>();
        for(int i=0;i<el.size();i++)
        {
            String temp=el.get(i).getText();
         
            if(!temp.isBlank())
            {
                text.add(temp);
            }
        }
        List<String> unique= new ArrayList<>(new HashSet<>(text));

        for(int i=0;i<unique.size();i++)

        {
            if(unique.get(i).contains("Shoes")||unique.get(i).contains("Watches"))
            {
                System.out.println(unique.get(i));
            }
        }

By Using Stream API(Java 8)

 el.stream().map(e->e.getText()).filter(s->!s.isBlank()).distinct()
.filter(s->s.contains("Shoes")||s.contains("Watches")).forEach(s->System.out.println(s));

The code looks much cleaner and more readable. Lines of code were also reduced.

Result:

Use New Java Features In The Test Automation

3)Java Predicate

A predicate in general is a predefined functional interface that returns a boolean value. It is defined in Java. util.function package and contains different methods like isEqual(),negate(),and(),or() etc which helps in improving the code manageability. Java lambda expression simplifies the creation of Java predicates. Lambda expressions take in parameters and return values. In general, we can use predicate as per the below example.

1)Filter numbers whose values are less than 5.

public class JavaPredicate {

    public static void main(String[] args) {

        List<Integer> nums = List.of(2, 3, 1, 5, 6, 7, 8, 9, 12);

        Predicate<Integer> btf = n -> n < 5;

        nums.stream().filter(btf).forEach(System.out::println);
    }
}

How can we utilize predicate in Test Automation? Suppose we have to validate certain conditions in our framework like after a certain period a web element is visible or not or an element is enabled or not. In such scenarios, we get either True or False and based on that, our script passes or fails.

1)Create a new class name as Validation and write a custom method that accepts the predicate as an argument and returns the expected result.


public class Validation {

    private final BooleanSupplier condition;
    private final long waitSeconds = 60;

    public Validation(BooleanSupplier condition) {
        this.condition = condition;
    }
    public static boolean waitFor(BooleanSupplier predicate) {
        return new Validation(predicate).waitForConditionToBeMet();
    }

2)Validate whether a certain field is visible on the webpage or not.

public void TestJava(){
      FrameworkConfig config= ConfigFactory.create(FrameworkConfig.class);

        WebDriver driver= LocalDriverFactory.getDriver();
        driver.get("https://www.myntra.com/");
        Assert.assertTrue(Validation.waitFor(() -> driver.findElement(By.xpath("//h4[normalize-space()='DEAL OF THE DAY']")).isDisplayed()));

}

4)Switch Expression in Java 12

We can now directly assign a value to a variable based on the result of the switch processing without using Break or default statements.

public static Response executeMethod(String endpoint, HttpMethod method){
 
    Response response = switch(method){
        case GET -> request.get(endpoint);
        case POST -> request.post(endpoint);
        case PUT -> request.put(endpoint);
        case PATCH -> request.patch(endpoint);
        case DELETE -> request.delete(endpoint);
    }
 
    response.then().log().all();
    return response;
}

Apart from all these features, there are several new enhancements available with the latest version of Java. By using this we can improve the readability of our test automation code.

5)Pattern Matching Of InstanceOf in Java 14

The Instance of operator in Java is used to check if an instance belongs to a class, subclass or interface. In the traditional approach, we used to check the instanceOf operator followed by the cast.

import org.openqa.selenium.WebElement;

public class TestAutomationScript {

    public void performAction(WebElement element) {
        if (element instanceof WebElement) {
            // Do something with the WebElement
            System.out.println("This is a WebElement");
        }
        // Other actions...
    }
}

From Java 14 we can combine the instanceOf operator with a cast, and Java will automatically cast the object to the desired type if the check passes. This helps to make code more concise and readable:

public void performAction(Object object) {
        if (object instanceof WebElement element) {
            System.out.println("This is a WebElement");
            element.click(); // Example of using WebElement method
        }
        
    }

Discover more from AutomationQaHub

Subscribe now to keep reading and get access to the full archive.

Continue reading