Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / Javascript

Design Grid Control Automated Tests Part 1

5.00/5 (2 votes)
21 Mar 2016Ms-PL6 min read 10.8K  
Detailed explanation how to design proper automated tests for grid controls. Includes examples for unique identifier and text columns.

Introduction

Once upon a time, I showed you how you can automate complex custom-tuned controls like a grid. You can read about it in my article Automate Telerik Kendo Grid with WebDriver and JavaScript. 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 be able to run against an empty DB. In this publication, I am going to share my opinion about writing decent grid control's automated tests. In the first part of this mini-series, I am going to talk about how to automate ID and text columns.

Image 1

Examples Explained

In the code examples, I am going to automate one of the demos of the Kendo Grid Control. To be able to create a 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 am going to 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 be able to get/insert/update/delete entities.

Image 2

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

C#
private void WaitForGridToLoad(int expectedCount, KendoGrid grid)
{
    this.Until(
        () =>
        {
            var items = grid.GetItems<GridItem>();
            return expectedCount == items.Count;
        });
}
            
private void WaitForGridToLoadAtLeast(int expectedCount, KendoGrid grid)
{
    this.Until(
        () =>
        {
            var items = grid.GetItems<GridItem>();
            return items.Count >= expectedCount;
        });
}
            
private void Until(
    Func<bool> condition, 
    int timeout = 10, 
    string exceptionMessage = "Timeout exceeded.", 
    int retryRateDelay = 50)
{
    DateTime start = DateTime.Now;
    while (!condition())
    {
        DateTime now = DateTime.Now;
        double totalSeconds = (now - start).TotalSeconds;
        if (totalSeconds >= timeout)
        {
            throw new TimeoutException(exceptionMessage);
        }
        Thread.Sleep(retryRateDelay);
    }
}

Until is a utility method that accepts a condition as C# Func that returns a bool. It will wait a specified amount of time and will try again after a couple of milliseconds (also configurable). We are going to use the WaitForGridToLoad function after a JavaScript filter is applied. It will wait for a specific amount of items to be present on the grid. The another method WaitForGridToLoadAtLeast does almost the same thing, except the number of loaded items can be greater than the specified one.

Design Tests- Unique Identifier 'ID' Column

There are six filters that need to be automated- EqualTo, NotEqualTo, GreaterThan, GreaterThanOrEqualTo, LessThan and LessThanOrEqualTo. Also, an additional test should be added to verify that the clear filter functionality is working as expected.

Order ID EqualTo Filter

C#
[TestMethod]
public void OrderIdEqualToFilter()
{
    this.driver.Navigate().GoToUrl(@"http://demos.telerik.com/kendo-ui/grid/frozen-columns");
    var kendoGrid = new KendoGrid(this.driver, this.driver.FindElement(By.Id("grid")));
    var newItem = this.CreateNewItemInDb();

    kendoGrid.Filter(
        OrderIdColumnName, 
        Enums.FilterOperator.EqualTo, 
        newItem.OrderId.ToString());           
    this.WaitForGridToLoad(1, kendoGrid);
    var items = kendoGrid.GetItems<Order>();
        
    Assert.AreEqual(1, items.Count);
}

First, we create a new item in the DB. As the order ID is unique, we can filter directly on it, and we expect that only one object should 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 NotEqualTo Filter

C#
[TestMethod]
public void OrderIdNotEqualToFilter()
{
    this.driver.Navigate().GoToUrl(@"http://demos.telerik.com/kendo-ui/grid/frozen-columns");
    var kendoGrid = new KendoGrid(this.driver, this.driver.FindElement(By.Id("grid")));
            
    var newItem = this.CreateNewItemInDb();
    var secondNewItem = this.CreateNewItemInDb(newItem.ShipName);
            
    kendoGrid.Filter(
        new GridFilter(
            OrderIdColumnName,
            Enums.FilterOperator.NotEqualTo, 
            secondNewItem.OrderId.ToString()),
        new GridFilter(
            ShipNameColumnName,
            Enums.FilterOperator.EqualTo, 
            secondNewItem.ShipName));
    this.WaitForGridToLoadAtLeast(1, kendoGrid);
    var results = kendoGrid.GetItems<Order>();
            
    Assert.AreEqual(newItem.OrderId, 
    results.FirstOrDefault(x => x.ShipName == newItem.ShipName).OrderId);
    Assert.IsTrue(results.Count() == 1);
}

This test has a little bit trickier arrange phase. 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 NotEqualTo OrderId. Only the first item should be shown on the grid.

Order ID GreaterThanOrEqualTo Filter

C#
[TestMethod]
public void OrderIdGreaterThanOrEqualToFilter()
{
    this.driver.Navigate().GoToUrl(@"http://demos.telerik.com/kendo-ui/grid/frozen-columns");
    var kendoGrid = new KendoGrid(this.driver, this.driver.FindElement(By.Id("grid")));

    var newItem = this.CreateNewItemInDb();
    var secondNewItem = this.CreateNewItemInDb(newItem.ShipName);
            
    kendoGrid.Filter(
        new GridFilter(
            OrderIdColumnName, 
            Enums.FilterOperator.GreaterThanOrEqualTo,
            newItem.OrderId.ToString()),
        new GridFilter(
            ShipNameColumnName, 
        Enums.FilterOperator.EqualTo, 
        newItem.ShipName));
    this.WaitForGridToLoadAtLeast(2, kendoGrid);
    var results = kendoGrid.GetItems<Order>();

    Assert.AreEqual(secondNewItem.OrderId, 
           results.FirstOrDefault(x => x.ShipName == secondNewItem.ShipName).OrderId);
    Assert.AreEqual(newItem.OrderId, 
           results.FirstOrDefault(x => x.ShipName == newItem.ShipName).OrderId);
    Assert.IsTrue(results.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. Filtering by shipping name displays only the two items. After that, we apply the GreaterThanOrEqualTo filter by OrderId. We assume that nothing will change, and these two elements will be still visible in the grid.

Order ID GreaterThan Filter

C#
[TestMethod]
public void OrderIdGreaterThanFilter()
{
    this.driver.Navigate().GoToUrl(@"http://demos.telerik.com/kendo-ui/grid/frozen-columns");
    var kendoGrid = new KendoGrid(this.driver, this.driver.FindElement(By.Id("grid")));
            
    var newItem = this.CreateNewItemInDb();
    var secondNewItem = this.CreateNewItemInDb(newItem.ShipName);
            
    kendoGrid.Filter(
        new GridFilter(
            OrderIdColumnName, 
            Enums.FilterOperator.GreaterThan, 
            newItem.OrderId.ToString()),
        new GridFilter(
            ShipNameColumnName, 
            Enums.FilterOperator.EqualTo, 
            newItem.ShipName));
    this.WaitForGridToLoadAtLeast(1, kendoGrid);
    var results = kendoGrid.GetItems<Order>();
            
    Assert.AreEqual(secondNewItem.OrderId, 
    results.FirstOrDefault(x => x.ShipName == secondNewItem.ShipName).OrderId);
    Assert.IsTrue(results.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 LessThanOrEqualTo Filter

C#
[TestMethod]
public void OrderIdLessThanOrEqualToFilter()
{
    this.driver.Navigate().GoToUrl(@"http://demos.telerik.com/kendo-ui/grid/frozen-columns");
    var kendoGrid = new KendoGrid(this.driver, this.driver.FindElement(By.Id("grid")));
            
    var newItem = this.CreateNewItemInDb();
    var secondNewItem = this.CreateNewItemInDb(newItem.ShipName);
            
    kendoGrid.Filter(
        new GridFilter(
            OrderIdColumnName, 
            Enums.FilterOperator.LessThanOrEqualTo, 
            secondNewItem.OrderId.ToString()),
        new GridFilter(
            ShipNameColumnName, 
            Enums.FilterOperator.EqualTo, 
            newItem.ShipName));
    this.WaitForGridToLoadAtLeast(2, kendoGrid);
    var results = kendoGrid.GetItems<Order>();
            
    Assert.AreEqual(newItem.OrderId, 
           results.FirstOrDefault(x => x.ShipName == newItem.ShipName).OrderId);
    Assert.AreEqual(secondNewItem.OrderId, 
           results.Last(x => x.ShipName == secondNewItem.ShipName).OrderId);
    Assert.IsTrue(results.Count() == 2);
}

It is almost the same as the test for the GreaterThanOrEqualTo 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 LessThan Filter

C#
[TestMethod]
public void OrderIdLessThanFilter()
{
    this.driver.Navigate().GoToUrl(@"http://demos.telerik.com/kendo-ui/grid/frozen-columns");
    var kendoGrid = new KendoGrid(this.driver, this.driver.FindElement(By.Id("grid")));
            
    var newItem = this.CreateNewItemInDb();
    var secondNewItem = this.CreateNewItemInDb(newItem.ShipName);
            
    kendoGrid.Filter(
        new GridFilter(
            OrderIdColumnName, 
            Enums.FilterOperator.LessThan, 
            secondNewItem.OrderId.ToString()),
        new GridFilter(
            ShipNameColumnName, 
            Enums.FilterOperator.EqualTo, 
            secondNewItem.ShipName));
    this.WaitForGridToLoadAtLeast(1, kendoGrid);
    var results = kendoGrid.GetItems<Order>();
            
    Assert.AreEqual(newItem.OrderId, 
    results.FirstOrDefault(x => x.ShipName == newItem.ShipName).OrderId);
    Assert.IsTrue(results.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

C#
[TestMethod]
public void OrderIdClearFilter()
{
    this.driver.Navigate().GoToUrl(@"http://demos.telerik.com/kendo-ui/grid/frozen-columns");
    var kendoGrid = new KendoGrid(this.driver, this.driver.FindElement(By.Id("grid")));
    var newItem = this.CreateNewItemInDb();
    var secondNewItem = this.CreateNewItemInDb(newItem.ShipName);
            
    kendoGrid.Filter(
        OrderIdColumnName, 
        Enums.FilterOperator.EqualTo, 
        newItem.OrderId.ToString());
    this.WaitForGridToLoad(1, kendoGrid);
    kendoGrid.RemoveFilters();
            
    this.WaitForGridToLoadAtLeast(1, kendoGrid);
    var results = kendoGrid.GetItems<Order>();
    Assert.IsTrue(results.Count() > 1);
}

The first part of the test is identical to the one for the EqualTo filter. After a single item is displayed, we remove all filters and expect that more items should be shown. As the test should be capable of being run against an empty DB, we create a second object before hand.

Image 3

Design Tests- Shipping Name 'Text' Column

There are six filters that need to be automated- EqualTo, NotEqualTo, Contains, NotContains, StartsWith and EndsWith. Also, an additional test should be added to verify that the clear filter functionality is working as expected.

Shipping Name EqualTo Filter

C#
[TestMethod]
public void ShipNameEqualToFilter()
{
    this.driver.Navigate().GoToUrl(@"http://demos.telerik.com/kendo-ui/grid/filter-row");
    var kendoGrid = new KendoGrid(this.driver, this.driver.FindElement(By.Id("grid")));
    var newItem = this.CreateNewItemInDb();

    kendoGrid.Filter(ShipNameColumnName, Enums.FilterOperator.EqualTo, newItem.ShipName);
    this.WaitForGridToLoad(1, kendoGrid);
    var items = kendoGrid.GetItems<GridItem>();
            
    Assert.AreEqual(1, items.Count);
}

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

Shipping Name NotEqualTo Filter

C#
[TestMethod]
public void ShipNameNotEqualToFilter()
{
    this.driver.Navigate().GoToUrl(@"http://demos.telerik.com/kendo-ui/grid/filter-row");
    var kendoGrid = new KendoGrid(this.driver, this.driver.FindElement(By.Id("grid")));
            
    var newItem = this.CreateNewItemInDb();
            
    kendoGrid.Filter(
        new GridFilter(ShipNameColumnName, Enums.FilterOperator.NotEqualTo, newItem.ShipName),
        new GridFilter(OrderIdColumnName, Enums.FilterOperator.EqualTo, newItem.OrderId));
    this.WaitForGridToLoad(0, kendoGrid);
    var items = kendoGrid.GetItems<GridItem>();
            
    Assert.AreEqual(0, items.Count);
}

We apply two filters. The first filter by ID should leave only the newly created item. We expect that the second filter by NotEqualTo shipping name should empty the grid.

Shipping Name Contains Filter

C#
[TestMethod]
public void ShipNameContainsFilter()
{
    this.driver.Navigate().GoToUrl(@"http://demos.telerik.com/kendo-ui/grid/filter-row");
    var kendoGrid = new KendoGrid(this.driver, this.driver.FindElement(By.Id("grid")));
    string shipName = Guid.NewGuid().ToString();
    shipName = shipName.TrimStart(shipName.First()).TrimEnd(shipName.Last());
    var newItem = this.CreateNewItemInDb(shipName);          

    kendoGrid.Filter(ShipNameColumnName, Enums.FilterOperator.Contains, newItem.ShipName);
    this.WaitForGridToLoad(1, kendoGrid);
    var items = kendoGrid.GetItems<GridItem>();
            
    Assert.AreEqual(1, items.Count);
}

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

Shipping Name NotContains Filter

C#
[TestMethod]
public void ShipNameNotContainsFilter()
{
    this.driver.Navigate().GoToUrl(@"http://demos.telerik.com/kendo-ui/grid/filter-row");
    var kendoGrid = new KendoGrid(this.driver, this.driver.FindElement(By.Id("grid")));            
          
    string shipName = Guid.NewGuid().ToString();
    shipName = shipName.TrimStart(shipName.First()).TrimEnd(shipName.Last());
    var newItem = this.CreateNewItemInDb(shipName);

    kendoGrid.Filter(
        new GridFilter(
            ShipNameColumnName, 
            Enums.FilterOperator.NotContains, 
            newItem.ShipName),
        new GridFilter(
            OrderIdColumnName, 
            Enums.FilterOperator.EqualTo, 
            newItem.OrderId.ToString()));
    this.WaitForGridToLoad(0, kendoGrid);
    var items = kendoGrid.GetItems<GridItem>();
            
    Assert.AreEqual(0, items.Count);
}

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

Shipping Name StartsWith Filter

C#
[TestMethod]
public void ShipNameStartsWithFilter()
{
    this.driver.Navigate().GoToUrl(@"http://demos.telerik.com/kendo-ui/grid/filter-row");
    var kendoGrid = new KendoGrid(this.driver, this.driver.FindElement(By.Id("grid")));

    string shipName = Guid.NewGuid().ToString();
    shipName = shipName.TrimEnd(shipName.Last());
    var newItem = this.CreateNewItemInDb(shipName);

    kendoGrid.Filter(ShipNameColumnName, Enums.FilterOperator.StartsWith, newItem.ShipName);
    this.WaitForGridToLoad(1, kendoGrid);
    var items = kendoGrid.GetItems<GridItem>();
            
    Assert.AreEqual(1, items.Count);
}

To be sure that the filter is different from the Contains filter, we trim the end of the shipping name.

Shipping Name EndsWith Filter

C#
[TestMethod]
public void ShipNameEndsWithFilter()
{
    this.driver.Navigate().GoToUrl(@"http://demos.telerik.com/kendo-ui/grid/filter-row");
    var kendoGrid = new KendoGrid(this.driver, this.driver.FindElement(By.Id("grid")));

    string shipName = Guid.NewGuid().ToString();
    shipName = shipName.TrimStart(shipName.First());
    var newItem = this.CreateNewItemInDb(shipName);

    kendoGrid.Filter(ShipNameColumnName, Enums.FilterOperator.EndsWith, newItem.ShipName);
    this.WaitForGridToLoad(1, kendoGrid);
    var items = kendoGrid.GetItems<GridItem>();
            
    Assert.AreEqual(1, items.Count);
}

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

Shipping Name Clear Filter

C#
[TestMethod]
public void ShipNameClearFilter()
{
    this.driver.Navigate().GoToUrl(@"http://demos.telerik.com/kendo-ui/grid/filter-row");
    var kendoGrid = new KendoGrid(this.driver, this.driver.FindElement(By.Id("grid")));
            
    kendoGrid.Filter(
        ShipNameColumnName, 
        Enums.FilterOperator.StartsWith, 
        Guid.NewGuid().ToString());
    this.WaitForGridToLoad(0, kendoGrid);
    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 be able to run the test against an empty DB, we create a new item at the beginning of the test.

 

The post Design Grid Control Automated Tests Part 1 appeared first on Automate The Planet.

All images are purchased from DepositPhotos.com and cannot be downloaded and used for free.
License Agreement

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)