Skip to content

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 programming 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

forEach is used 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 simply 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 of time a web element is visible or not or an element is enabled or not. In such scenarios, we get either True or False and on the basis of 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.