Design Grid Control Automated Tests with Java Part 1

Design Grid Control Automated Tests with Java Part 1

In the previous article, I showed you how to automate complex custom-tuned controls like a grid. In my article Automate Telerik Kendo Grid with WebDriver and JavaScript, you can read about it. However, this is just the beginning. The hardest part is figuring out how to design proper automated tests for every grid’s column. It is even more challenging if you want your tests to run against an empty DB. In this publication, I will share my opinion about writing decent grid control automated tests. In the first part of this mini-series, I will talk about how to automate ID and text columns.

Examples Explained

In the code examples, I will automate one of the demos of the Kendo Grid Control. To create proper automation of controls like this, you need an API that enables you to perform basic CRUD operations against the DB (table) that the grid gets its data. For simplicity, I will use dummy wrapper methods in the examples. In a real-world project, you will need to replace the dummy code with a DB repository or a web service to get/insert/update/delete entities.

Kendo Grid Demo

As you will notice in the examples, I will use the so-called KendoGrid element and all of its methods. I suggest you read all about it in my article- Automate Telerik Kendo Grid with WebDriver and JavaScript. Additionally, we will need a couple of additional methods to run the tests properly. 

private void waitForGridToLoad(int expectedCount, KendoGrid grid) {
  wait.until(x -> {
    List < GridItem > items = grid.getItems();
    return expectedCount == items.stream().count();
  });
}
private void waitForGridToLoadAtLeast(int expectedCount, KendoGrid grid) {
  wait.until(x -> {
    List < GridItem > items = grid.getItems();
    return items.stream().count() >= expectedCount;
  });
}

We use until a method that comes from the WebDriverWait class. It will wait a specified amount of time and try again after a couple of milliseconds. For example, we will use the waitForGridToLoad function after applying a JavaScript filter. It will wait for a specific number of items on the grid. waitForGridToLoadAtLeast does almost the same thing, except the number of loaded items can be greater than specified.

Design Tests- Unique Identifier ‘ID’ Column

Six filters need to be automated- EQUAL_TO, NOT_EQUAL_TO, GREATER_THAN, GREATER_THAN_OR_EQUAL_TO, LESS_THAN, and LESS_THAN_OR_EQUAL_TO. Also, an additional test should be added to verify that the clear filter functionality is working as expected.

Order ID EQUAL_TO Filter

@Test
public void orderIdEqualToFilter() throws Exception {
  var newItem = CreateNewItemInDb();
  kendoGrid.filter(OrderIdColumnName, FilterOperator.EQUAL_TO, newItem.getOrderId());
  waitForGridToLoad(1, kendoGrid);
  List < GridItem > items = kendoGrid.getItems();
  Assert.assertEquals(items.stream().count(), 1);
}

First, we create a new item in the DB. As the order ID is unique, we can filter directly on it, and we expect only one object to be displayed. After the filtration, we wait for the grid to load a single item, get all the elements, and assert that only one item is present.

Order ID NOT_EQUAL_TO Filter

@Test
public void orderIdNotEqualToFilter() throws Exception {
  // Create new item with unique ship name;
  var newItem = CreateNewItemInDb();
  // Create second new item with the same unique shipping name
  var secondNewItem = CreateNewItemInDb(newItem.getShipName());
  // Filter by the larger orderId but also by the second unique column in this case shipping name
  kendoGrid.filter(
    new GridFilter(OrderIdColumnName, FilterOperator.NOT_EQUAL_TO, secondNewItem.getOrderId()),
    new GridFilter(ShipNameColumnName, FilterOperator.EQUAL_TO, secondNewItem.getShipName()));
  waitForGridToLoadAtLeast(1, kendoGrid);
  List < Order > results = kendoGrid.getItems();
  Assert.assertEquals(results.stream().filter(x -> x.getShipName() == newItem.getShipName()).findFirst().get().getOrderId(), newItem.getOrderId());
  Assert.assertTrue(results.stream().count() == 1);
}

This test has a little bit trickier arrange phase. First, we create two new items. We assign them a unique shipping name that is the same for both. Then we apply two filters, one by the shipping name. This way, only these two items should be displayed. After that, we filter by NOT_EQUAL_TO OrderId. Only the first item should be shown on the grid.

Order ID GREATER_THAN_OR_EQUAL_TO Filter

@Test
public void orderIdGreaterThanOrEqualToFilter() throws Exception {
  // Create new item with unique ship name;
  var newItem = CreateNewItemInDb();
  // Create second new item with the same unique shipping name
  var secondNewItem = CreateNewItemInDb(newItem.getShipName());
  // When we filter by the second unique column ShippingName, only one item will be displayed.
  // Once we apply the second not equal to filter the grid should be empty.
  kendoGrid.filter(
    new GridFilter(OrderIdColumnName, FilterOperator.GREATER_THAN_OR_EQUAL_TO, newItem.getOrderId()),
    new GridFilter(ShipNameColumnName, FilterOperator.EQUAL_TO, newItem.getShipName()));
  waitForGridToLoadAtLeast(2, kendoGrid);
  List < Order > results = kendoGrid.getItems();
  Assert.assertEquals(results.stream().filter(
    x -> x.getShipName() == secondNewItem.getShipName()).findFirst().get().getOrderId(), secondNewItem.getOrderId());
  Assert.assertEquals(results.stream().filter(
    x -> x.getShipName() == newItem.getShipName()).findFirst().get().getOrderId(), newItem.getOrderId());
  Assert.assertTrue(results.stream().count() == 2);
}

Again we create two items with an identical shipping name. Usually, the unique identifiers are incremental, meaning that the new IDs will be bigger than the previous ones. So we apply two filters again. First, we filter by shipping name, displaying only the two items. After that, we use the GREATER_THAN_OR_EQUAL_TO filter by OrderId. Furthermore, we assume that nothing will change, and these two elements will still be visible in the grid.

Order ID GREATER_THAN Filter

@Test
public void orderIdGreaterThanFilter() throws Exception {
  // Create new item with unique ship name;
  var newItem = CreateNewItemInDb();
  // Create second new item with the same unique shipping name
  var secondNewItem = CreateNewItemInDb(newItem.getShipName());
  // Filter by the smaller orderId but also by the second unique column in this case shipping name
  kendoGrid.filter(
    new GridFilter(OrderIdColumnName, FilterOperator.GREATER_THAN, newItem.getOrderId()),
    new GridFilter(ShipNameColumnName, FilterOperator.EQUAL_TO, newItem.getShipName()));
  waitForGridToLoadAtLeast(1, kendoGrid);
  List < Order > results = kendoGrid.getItems();
  Assert.assertEquals(results.stream().filter(
    x -> x.getShipName() == secondNewItem.getShipName()).findFirst().get().getOrderId(), secondNewItem.getOrderId());
  Assert.assertTrue(results.stream().count() == 1);
}

Almost identical to the previous example, except, in the end, we verify that a single item is present in the grid, the one with the bigger ID.

Order ID LESS_THAN_OR_EQUAL_TO Filter

@Test
public void orderIdLessThanOrEqualToFilter() throws Exception {
  // Create new item with unique ship name;
  var newItem = CreateNewItemInDb();
  // Create second new item with the same unique shipping name
  var secondNewItem = CreateNewItemInDb(newItem.getShipName());
  // Filter by the larger orderId but also by the second unique column in this case shipping name
  kendoGrid.filter(
    new GridFilter(OrderIdColumnName, FilterOperator.LESS_THAN_OR_EQUAL_TO, secondNewItem.getOrderId()),
    new GridFilter(ShipNameColumnName, FilterOperator.EQUAL_TO, newItem.getShipName()));
  waitForGridToLoadAtLeast(2, kendoGrid);
  List < Order > results = kendoGrid.getItems();
  Assert.assertEquals(results.stream().filter(
    x -> x.getShipName() == newItem.getShipName()).findFirst().get().getOrderId(), newItem.getOrderId());
  Assert.assertEquals(results.stream().filter(
      x -> x.getShipName() == secondNewItem.getShipName()).skip(results.stream().count() - 1)
    .findFirst().get().getOrderId(), secondNewItem.getOrderId());
  Assert.assertTrue(results.stream().count() == 2);
}

It is almost the same as the test for the GREATER_THAN_OR_EQUAL_TO filter, except this time we filter by the OrderId of the second item, which is bigger. In the end, two items should be displayed in the grid.

Order ID LESS_THAN Filter

@Test
public void orderIdLessThanFilter() throws Exception {
  // Create new item with unique ship name;
  var newItem = CreateNewItemInDb();
  // Create second new item with the same unique shipping name
  var secondNewItem = CreateNewItemInDb(newItem.getShipName());
  // Filter by the larger orderId but also by the second unique column in this case shipping name
  kendoGrid.filter(
    new GridFilter(OrderIdColumnName, FilterOperator.LESS_THAN, secondNewItem.getOrderId()),
    new GridFilter(ShipNameColumnName, FilterOperator.EQUAL_TO, secondNewItem.getShipName()));
  waitForGridToLoadAtLeast(1, kendoGrid);
  List < Order > results = kendoGrid.getItems();
  Assert.assertEquals(results.stream().filter(
    x -> x.getShipName() == newItem.getShipName()).findFirst().get().getOrderId(), newItem.getOrderId());
  Assert.assertTrue(results.stream().count() == 1);
}

The difference is that we change the type of the filter, and only a single element should be visible on the grid.

Order ID Clear Filter

@Test
public void orderIdClearFilter() throws Exception {
  // Create new item with unique ship name;
  var newItem = CreateNewItemInDb();
  // Make sure that we have at least 2 items if the grid is empty. The tests are designed to run against empty DB.
  var secondNewItem = CreateNewItemInDb(newItem.getShipName());
  kendoGrid.filter(OrderIdColumnName, FilterOperator.EQUAL_TO, newItem.getOrderId());
  waitForGridToLoad(1, kendoGrid);
  kendoGrid.removeFilters();
  waitForGridToLoadAtLeast(1, kendoGrid);
  List < Order > results = kendoGrid.getItems();
  Assert.assertTrue(results.stream().count() > 1);
}

The first part of the test is identical to the EQUAL_TO filter. After a single item is displayed, we remove all filters and expect more items to be shown. As the test should be run against an empty DB, we create a second object beforehand.

Design Tests- Shipping Name ‘Text’ Column

Six filters must be automated- EQUAL_TO, NOT_EQUAL_TO, CONTAINS, NOT_CONTAINS, STARTS_WITH, and ENDS_WITH. Also, an additional test should be added to verify that the clear filter functionality is working as expected.

Shipping Name EQUAL_TO Filter

@Test
public void shipNameEqualToFilter() throws Exception {
  var newItem = createNewItemInDb();
  kendoGrid.filter(GridColumns.SHIP_NAME, FilterOperator.EQUAL_TO, newItem.getShipName());
  waitForGridToLoad(1, kendoGrid);
  List < GridItem > items = kendoGrid.getItems();
  Assert.assertEquals(items.stream().count(), 1);
}

Create a new item with a unique shipping name. After we filter by it, only a single element should be displayed.

Shipping Name NOT_EQUAL_TO Filter

@Test
public void shipNameNotEqualToFilter() throws Exception {
  // Apply combined filter. First filter by ID and than by ship name (not equal filter).
  // After the first filter there is only one element when we apply the second we expect 0 elements.
  var newItem = createNewItemInDb();
  kendoGrid.filter(
    new GridFilter(GridColumns.SHIP_NAME, FilterOperator.NOT_EQUAL_TO, newItem.getShipName()),
    new GridFilter(GridColumns.ORDER_ID, FilterOperator.EQUAL_TO, newItem.getOrderId().toString()));
  waitForGridToLoad(0, kendoGrid);
  List < GridItem > items = kendoGrid.getItems();
  Assert.assertEquals(items.stream().count(), 0);
}

We apply two filters. The first filter by ID should leave only the newly created item. We set the second filter to NOT_EQUAL_TO shipping name to empty the grid.

Shipping Name CONTAINS Filter

@Test
public void shipNameContainsFilter() throws Exception {
  var shipName = UUID.randomUUID().toString();
  // Remove first and last letter
  shipName = removeLastChar(removeFirstChar(shipName));
  var newItem = createNewItemInDb(shipName);
  kendoGrid.filter(GridColumns.SHIP_NAME, FilterOperator.CONTAINS, newItem.getShipName());
  waitForGridToLoad(1, kendoGrid);
  List < GridItem > items = kendoGrid.getItems();
  Assert.assertEquals(items.stream().count(), 1);
}

We trim the start and the end of the unique shipping name. If a single element is visible after the filter, this means that the filter works correctly.

Shipping Name NOT_CONTAINS Filter

@Test
public void shipNameNotContainsFilter() throws Exception {
  // Remove first and last letter
  var shipName = UUID.randomUUID().toString();
  shipName = removeLastChar(removeFirstChar(shipName));
  var newItem = createNewItemInDb(shipName);
  // Apply combined filter. First filter by ID and than by ship name (not equal filter).
  // After the first filter there is only one element when we apply the second we expect 0 elements.
  kendoGrid.filter(
    new GridFilter(GridColumns.SHIP_NAME, FilterOperator.NOT_CONTAINS, newItem.getShipName()),
    new GridFilter(GridColumns.ORDER_ID, FilterOperator.EQUAL_TO, newItem.getOrderId().toString()));
  waitForGridToLoad(0, kendoGrid);
  List < GridItem > items = kendoGrid.getItems();
  Assert.assertEquals(items.stream().count(), 0);
}

It is identical to the test for the EQUAL_TO filter, except we trim the start and the end of the shipping name.

Shipping Name STARTS_WITH Filter

@Test
public void shipNameStartsWithFilter() throws Exception {
  // Remove last letter
  var shipName = UUID.randomUUID().toString();
  shipName = removeFirstChar(shipName);
  var newItem = createNewItemInDb(shipName);
  kendoGrid.filter(GridColumns.SHIP_NAME, FilterOperator.STARTS_WITH, newItem.getShipName());
  waitForGridToLoad(1, kendoGrid);
  List < GridItem > items = kendoGrid.getItems();
  Assert.assertEquals(items.stream().count(), 1);
}

To ensure that the filter is different from the CONTAINS filter, we trim the end of the shipping name.

Shipping Name ENDS_WITH Filter

@Test
public void shipNameEndsWithFilter() throws Exception {
  // Remove first letter
  var shipName = UUID.randomUUID().toString();
  shipName = removeFirstChar(shipName);
  var newItem = createNewItemInDb(shipName);
  kendoGrid.filter(GridColumns.SHIP_NAME, FilterOperator.ENDS_WITH, newItem.getShipName());
  waitForGridToLoad(1, kendoGrid);
  List < GridItem > items = kendoGrid.getItems();
  Assert.assertEquals(items.stream().count(), 1);
}

To be ensure that the filter is different from the CONTAINS filter, we trim the start of the shipping name.

Shipping Name Clear Filter

@Test
public void shipNameClearFilter() throws Exception {
  createNewItemInDb();
  // Filter by GUID and we know we wait the grid to be empty
  kendoGrid.filter(GridColumns.SHIP_NAME, FilterOperator.STARTS_WITH, UUID.randomUUID().toString());
  waitForGridToLoad(0, kendoGrid);
  // Remove all filters and we expect that the grid will contain at least 1 item.
  kendoGrid.removeFilters();
  waitForGridToLoadAtLeast(1, kendoGrid);
}

We first apply a filter by some non-existing shipping name. After that, when we remove the filters, we expect more than one element to be displayed. To run the test against an empty DB, we create a new item at the beginning of the test.

Related Articles

Design Patterns, Web Automation Java

Mastering Parameterized Tests in JUnit with Selenium WebDriver

In the evolving landscape of software testing, efficiency and coverage are paramount. JUnit 5 introduces enhanced parameterized testing capabilities, allowing d

Mastering Parameterized Tests in JUnit with Selenium WebDriver

Web Automation Java

Shadow DOM: Locating Elements with XPath Workaround

In this post, we will go through the basics of shadow DOM, its use, benefits, and constraints, and we will analyse the solution for them. As an Automation Engin

Shadow DOM: Locating Elements with XPath Workaround

Java, Kotlin, Web Automation Java

30 Advanced WebDriver Tips and Tricks Kotlin Code

This is the next article from the WebDriver Series where I will share with you 30 advanced tips and tricks using Java code. I wrote similar articles separated i

30 Advanced WebDriver Tips and Tricks Kotlin Code

Java, Web Automation Java

WebDriver – Capture and Modify HTTP Traffic – Java Code

In the Web Automation Java Series, I share with you tips and tricks about how to implement various test automation scenarios using Java. In this article, I am g

WebDriver – Capture and Modify HTTP Traffic – Java Code

Web Automation Java

Design Grid Control Automated Tests with Java Part 2

In my previous article, Design Grid Control Automated Tests Part 1, I started this mini-series about writing decent grid control automated tests. In this second

Design Grid Control Automated Tests with Java Part 2

Resources, Web Automation Java

Most Complete Selenium WebDriver Kotlin Cheat Sheet

As you know, I am a big fan of Selenium WebDriver. You can find tones of useful Kotlin/Java code in my Web Automation Java Series. I lead automated testing cour

Most Complete Selenium WebDriver Kotlin Cheat Sheet
Anton Angelov

About the author

Anton Angelov is Managing Director, Co-Founder, and Chief Test Automation Architect at Automate The Planet — a boutique consulting firm specializing in AI-augmented test automation strategy, implementation, and enablement. He is the creator of BELLATRIX, a cross-platform framework for web, mobile, desktop, and API testing, and the author of 8 bestselling books on test automation. A speaker at 60+ international conferences and researcher in AI-driven testing and LLM-based automation, he has been recognized as QA of the Decade and Webit Changemaker 2025.