Many applications render data in tables; writing tests for table-based data is a very common task. Unless you approach it with a bit of preparation, it’s also a task that can easily result in you building very brittle tests.
Consider the following grid which displays a list of contacts after having taken actions elsewhere in the system. (I’m using a Telerik RadGrid for AJAX in this example, by the way.)
Perhaps one of our tests is to verify Jayne Cobb appears in the table. I can easily do that in two steps via a recorded step. Easy!
The problem is if the contents of that table ever change, this test will break. By default when working with table Test Studio (and every other recording tool!) will “hardwire” in that element’s find logic based on the position of that element in the table. In this specific case, Test Studio sees the table’s row has it’s own ID value, courtesy of the RadGrid control. We’ll use that ID value, plus a check that the tagname of that element is ‘tr’ to ensure we’re focusing on a table row. We can see this by looking at the definition of that element in the Element Repository.
If your test is that Jayne Cobb should always render in this row then that find logic is OK. That’s often not the case, though, so the test will break if the order changes, or if columns are added. Normally; however, we’re just interested that Jayne exists somewhere in the table. If that’s the case, then let’s get something a little less brittle.
Get the table itself in to the Element Repository so you can work with it in coded steps. Elements get added to the repository when you interact with the page when the Recorder is running; you can also explicitly add elements in manually so you can more easily work with them, or their child elements, later on.
From the recorder, highlight the element and select Add to Project Elements from the Elements menu.
Note that I’m getting a range of scopes for element selection via the additional blue selectors above—this is the additional functionality you get when using various Telerik controls. In this case I can select the specific cell, its row, the inner table view, or the outer grid.
Turn on the 'Prompt for element name before adding’ in the General tab of Project Settings. You’ll get the chance to use your own naming scheme for the element when it’s added.
As I mentioned above, you want to avoid “hardwiring” in selector/find logic for rows or cells. Instead, use a coded step to select the row you want to interact with from the table. It’s a snap!
RadGrid grid = Pages.DemoPage.Contacts_Table; HtmlTableRow jayne = grid.Find.TableRow("Cobb");
That's it! Grab the RadGrid from the element repository (the Pages object when you’re in code), then use one of the various Find methods to search for the row you want. In this case I’m simply looking for one row, so the approach above works nicely.
Just as you want to avoid hardwiring in row selection, avoid the same issue with cells you need to deal with in your target row. Using the same example we’ve been following, if we enable editing in the RadGrid we’ll get a display similar to this:
If I need to click the “Edit” link to validate an Update action, then the most stable way for me to do that is again via code. We’ll start with the same two lines from above, then find and click the anchor link within the Edit cell.
RadGrid grid = Pages.DemoPage.Contacts_Table; HtmlTableRow jayne = grid.Find.TableRow("Cobb"); HtmlAnchor edit = jayne.Find.ByContent<HtmlAnchor>("Edit"); edit.Click();
Question: The above tips all work great when your grid only has one page worth of data. How do you deal with paging?
Unless your test is specific to paging, or you flat out can’t get around it, set up your tests’ input so you can avoid paging. Narrow search criteria, use a baseline dataset, do anything you have to in order to have a stable set of data in the grid you’re working with. Yes, yes, you may have larger tests where you’re wanting to validate paging and other issues; however, in CRUD testing of grids you shouldn’t be fooling with this. Keep your tests focused and granular.
Paging brings all kinds of complexity in to the issue. Cheat and avoid it unless your tests are specifically around paging. In which case, cheat again and ensure you’re setting up the system beforehand to give you the most stable path possible.
Testing data in tables can be very difficult and brittle. Set yourself up for success by using a defined baseline dataset or narrow your tables’ displays to ensure you’re getting exactly what you’ll need to interact with.
At all costs, avoid hardwired row and cell selectors, and instead use coded steps to make sure you’re creating the most flexible, maintainable tests possible!
Subscribe to be the first to get our expert-written articles and tutorials for developers!