Using HashMaps in automated tests

Published by

on

HashMaps are one of those Java concepts that can be very useful in automation testing, but are not widely used, because they seem to be too complicated. A HashMap is nothing more than a collection of key/value pairs, where you can store test related data to access later in the tests. In this post i will go over the basics of a HashMap. And what better way to see what you can use it for than an example?

The very basics

Let’s go over a little bit of basics regarding a HashMap. What you need to know:

  • it’s a collection of key/value pairs
  • each key must be unique. You cannot have two items in the HashMap with the same key. However you can have the same value multiple times in the HashMap
  • each key and value can be Objects. This means you can either use String or Integer for their type, or even custom Objects you have in your project. From my experience however, String and Integer will be what you will use the most (the most complex thing i used for value type was List<String>, but it all depends on your project)
  • each key in the HashMap is of the same type, specified when the HashMap is initialized. Each value is of the same type, specified also upon initialization

Initialization

Creating an empty HashMap can easily be done as in the below example:

HashMap<K, V> theHashMap = new HashMap<>();

Here, K represents the type corresponding to the key, and V represents the type corresponding to the value. To create a HashMap where the keys are Strings and the values are Integer, the following initialization can be done:

HashMap<String, Integer> theStringIntegerHashMap = new HashMap<>();

To create a HashMap where both the keys and values are of type String:

HashMap<String, String> theStringHashMap = new HashMap<>();

Adding items to the HashMap

Adding a new pair of key-values can be done using the ‘put()’ method. It takes the following two parameters: the first one represents the key, while the second one represents the value of the pair you want to add.

For example, adding a new pair of String-String values to the ‘theStringHashMap’ can be done:

theStringHashMap.put("theNewKey", "theNewValue");

Getting an item from the HashMap

In order to work with a single item of the HashMap, whose key we know, we can use the ‘get()’ method, to which we need to provide the key we are interested in. It will return the value corresponding to the specified key. For example, calling the ‘get()’ method by providing the key ‘theNewKey’ (which was added in the above paragraph) is done:

theStringHashMap.get("theNewKey")

It will return the following String, which is the value from the pair where the key is ‘theNewKey’:

theNewValue

Checking the size of the HashMap

If the tests you are working on require you to compare the size of the HashMap to an expected size, you can do so by using the ‘size()’ method. This will return the number of key-value pairs allocated in the HashMap. Its’ usage is as follows:

theStringHashMap.size()

Example

The task

The above information is all you need in order to perform the task from this post. For this task, the following table represents a part of the webpage you need to test. It represents a shoe size conversion table, between the size measured in UK standard and the size measured in EU standard. These values are approximate and only for testing purposes.

For example, according to the table below, the corresponding EU size for the UK size 4 is 36.5. Similarly, for UK size 6 the EU value is 38.5.

The task is to check that the EU size for UK size 5.5 is 38.

UK EU
4 36.5
4.5 37
5.5 38
6 38.5
6.5 39.5

The HTML

Before we start building the tests, we need to take a look at the HTML which represents the table we need to work with. This will help us understand how to build our tests: what WebElements we need, how we will store the information read from the page, etc.

<table class="w3-table w3-bordered w3-card-4">
<tbody>
     <tr>
          <th>UK</th>
          <th>EU</th>
     </tr>
     <tr>
          <td style="text-align:center;">4</td>
          <td style="text-align:center;">36.5</td>
     </tr>
     <tr>
          <td style="text-align:center;">4.5</td>
          <td style="text-align:center;">37</td>
     </tr>
     <tr>
          <td style="text-align:center;">5.5</td>
          <td style="text-align:center;">38</td>
     </tr>
     <tr>
          <td style="text-align:center;">6</td>
          <td style="text-align:center;">38.5</td>
     </tr>
     <tr>
          <td style="text-align:center;">6.5</td>
          <td style="text-align:center;">39.5</td>
     </tr>
</tbody>
</table>

The PageObject class

Now that we looked at the HTML, we can create an entry in a new PageObject class created for the purpose of this test. We only need one List of WebElements, where each element of the List represents a row in the table. Actually we are storing all the ‘tr’ elements which are children of the ‘table’ element into this List.

@FindBy(css = "table tr")
public List<WebElement> tableRows;

At this point this List does not provide well formatted information we can work with, but it is perfectly fine, as we will identify each element from each row (each column) in the code where we will generate the HashMap. Read on.

The code

Before using HashMaps in our test class, we will need to import them by providing the following entry in our test class import section:

import java.util.HashMap;

Now, in the test method, we will need to work our magic. First, of course, the browser needs to be opened and the page loaded in the browser (parts i omit in this post but can be seen in the GitHub project where this example can be found). We now have access to each row in the shoe size table, but that information is not very well structured. We want to check that the EU size corresponding to UK size 5.5 is 38. We also want to do this in an elegant way, and have the information structured in a nice way. For this purpose, a HashMap will be useful.

Each key in the HashMap we will create will represent a size in UK, while the values will the be the corresponding size in EU. We will map each row in the HTML table to a key-value pair we will store in the HashMap. Therefore, as the table has 5 rows we are interested in (we don’t care about the header), our HashMap will have a size of 5 (it will store 5 key-value pairs).

Because the information in the table is numeric, we will use Double as the type for both the keys and the values of the HashMap. Let’s create an empty HashMap for storing the information from the table:

HashMap<Double, Double> sizeHashMap = new HashMap<>();

Now let’s look again at the HTML structure of a row of the table:

<tr> 
           <td style="text-align:center;">6</td> 
           <td style="text-align:center;">38.5</td> 
</tr>

In the List of WebElements (which we named ‘tableRows’), we stored eached <tr> HTML tag. But the information we need (the sizes) are in the two <td> children of each <tr> tag. Therefore, in order to read the sizes from the page with Selenium, we would need to have a handle to each <td> child of each <tr>, represented as a WebElement.

To generate these, we will first iterate over the List of WebElements we created in the PageObject class (called ‘tableRows’), except for the first item in this List. That is because the first item represents the header of the table and that does not represent useful data for our test. The iteration will be done as follows:

for (int i = 1; i < page.tableRows.size(); i++) {

Now, for each of these WebElements, representing a row, we will store the corresponding children (<td> elements) into a new List. We will find the children of each WebElement representing a row by calling ‘findElements(By.cssSelector(“td”))’ on the row WebElement:

 List<WebElement> td = page.tableRows.get(i).findElements(By.cssSelector("td"));

This means that for each WebElement representing a row, in the for loop, we will create a List of WebElements with size 2: the first element of the list will hold the UK size, while the second element of the list will hold the EU size.

Now, while still in the for loop, we will add a new item to the HashMap. This item will represent the UK and EU size corresponding to the current row, by specifying the key of the HashMap item to be the text of the first <td> row element (converted to Double), and the value to be the text of the second <td> row element (also converted to Double). Reading the values from the page will be done with Selenium’s ‘getText()’, while the conversion will be done (as per the Useful Type Conversions post i wrote a while back) using the ‘Double.parseDouble()’ method:

 sizeHashMap.put(Double.parseDouble(td.get(0).getText()), Double.parseDouble(td.get(1).getText()));

After the iteration over the entire List of row WebElements is finished, the HashMap will be populated with all the size information from the table.

Now, in order to check that the corresponding EU size for UK size 5.5 is 38, in an assertion, the HashMap value corresponding to key 5.5 will be compared against the expected value of 38:

assertEquals(38.0, sizeHashMap.get(5.5));

To put it all together:

HashMap<Double, Double> sizeHashMap = new HashMap<>();
for (int i = 1; i < page.tableRows.size(); i++) {
    List<WebElement> td = page.tableRows.get(i).findElements(By.cssSelector("td"));
    sizeHashMap.put(Double.parseDouble(td.get(0).getText()), Double.parseDouble(td.get(1).getText()));
}
System.out.println("sizeHashMap = " + sizeHashMap);
assertEquals(38.0, sizeHashMap.get(5.5));

And that concludes the task.

Further reading

For all the information regarding HashMaps please refer to the official documentation:

https://docs.oracle.com/javase/9/docs/api/java/util/HashMap.html 

The examples from this post can be found in GitHub under:

2 responses to “Using HashMaps in automated tests”

  1. […] Using HashMaps in automated tests – I’m a little testerAn interesting introduction to hashmaps and how they can be used in test automation. This can be a great way to store test data. […]

    Like

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Blog at WordPress.com.