Working with Data Presented in…
  • RSS Feed

Last modified on 12/6/2016 5:04 PM by User.

Working with Data Presented in Tables

A Solution to Working with Data Presented in Tables (Working with QTP and a WebTable)

Most modern applications present information in a tabular format, an example of which is shown in the screenshot below (for the OdinPortal web application):

There are a number of ways that test processes may wish to interact with this table, probably the most common is to find a row of information based on some type of search criteria and then retrieve an item of data from within that row.

e.g. Find the row containing j.smith@testing.com in the UserId column, then within that row get his DOB from the Date of Birth Column.

The above example with result in 03/12/1970, the question for an Axe Technician is how to implement this in the Axe platform so that it presents straightforwardly for the Tester but gives us the flexibility to work with the table.

Don’t try and do too much in one action

The secret to working with more complex data presentation formats is to break down the interaction into more than one step. Essentially in the example above, there are two activities going on:

·         Finding a Row

·         Retrieving Data from within that Row.

Think outside of the Box (or Table or Cell).

Another useful technique is to remember that you don’t have to be constrained by the object classes that the UI tools recognise, i.e. WebTable and WebCell. Within the Axe platform we have the ability to specify custom object classes that fit the needs of a specific testing situation. In this particular example we are really working with columns:

  • Find the row containing j.smith@testing.com in the UserId column
  • get his DOB from the Date of Birth Column

So what we really need here is the ability to work with column objects in the Axe subtest table.

Start with the Subtest Presentation

Here is a possible way of how we might specify the above example in an Axe subtest table:

[]AccountDetails

UserIdCol

DOBCol

 

action

action

data

action

data

set

find

j.smith@testing.com

val

03/12/1970

 Notice that we have introduced the notion of working with Column objects, UserIdCol and DOBCol, these refer to the Date of Birth Column and the UserID Column respectively.

We have also introduced a custom action here: find (in the example above, used for the UserIdCol), so let’s just recap what this is set of actions is essentially saying:

Find the value in the UserIDCol object that matches j.smith@testing.com and then validate the DOB matches the value 03/12/1970 in the DOBCol.

Creating Custom Object Map Entries

First let’s look at how to create the Object map entries for the column objects. For this we will need to use the Axe Object Map format (most tools like do not allow us to do this directly in their own object repository mechanism). In this case the objects we define in the Axe Object Map format co-exist with the standard QTP objects. Here is a suggested layout for the object map:

name

class

table

column

UserDetails.UserIdCol

WebTableColumn

UserTable

1

UserDetails.TitleCol

WebTableColumn

UserTable

2

UserDetails.NameCol

WebTableColumn

UserTable

3

UserDetails.GenderCol

WebTableColumn

UserTable

4

UserDetails.DOBCol

WebTableColumn

UserTable

5

Note the objects all exist under the UserDetails page (this is mapped as a standard object in the UI tool object map). We have introduced a custom class here WebTableColumn. It is up to us as technicians to name this class, so keep it logical, in this case these are Columns in a WebTable object, so the class is named WebTableColumn.

Note also that we have two properties for each object: table and column.

Table relates to the name of the overall WebTable object (the significance of which will become clear in the next section). Column refers to the column number as laid out in the table itself:

Remember to add the new object map to the Build Configuration File!

Now with the object map entries in place, we need to provide the action map entries for the find and get actions for the WebTableColumn class. Remember in the Axe Model that a Val action is really a combination of a get and a Val. So in this instance we need to only implement the get action for the WebTableColumn class, and use it in conjunction with a standard Val.

Creating Action Map Entries

Let’s work on the find action first, essentially this action needs to search a specific column in the table and find the row that contains the corresponding data. Fortunately in QTP there is a Method on the WebTable class that will do this for us neatly: GetRowWithCellText , documented in QTP as follows:

So the action map entry should be along the lines of:

class

action

command

WebTableColumn

find

curr_row = %REFERENCE%WebTable("&table&").GetRowWithCellText("%DATA%",&column&)

There are a few things to note here:

Firstly that this returns us a row number, so we have to store that number in a variable, in this case curr_row. Fortunately VBScript doesn’t require us to have pre-declared the variable in this instance, although we may need to do so for other langauges by overriding the _testInit or _testPrefix actions with the declaration.

Note also that in this case the WebTable object name will come from the table property of the object map entry: &table&

The Column that is being searched will also come from the object map, this time the column property: &column&

So for the following subtest table and object map entry:

UserIdCol

action

data

find

j.smith@testing.com

 

name

class

table

column

UserDetails.UserIdCol

WebTableColumn

UserTable

1

 

This will result in the following line of code:

curr_row = Browser("Browser").Page("UserDetails").WebTable("UserTable").GetRowWithCellText("j.smith@testing.com",1)

Next we need to ensure that the subsequent get action for the DOBCol returns the correct value. We can use the GetCellData method in QTP as follows in the action map:

class

action

command

WebTableColumn

get

value = %REFERENCE%WebTable("&table&").GetCellData(curr_row,&column&)

 Note here that as a custom get action the resultant value must be passed back to the Axe value variable. (This is so it can be used for subsequent val or save actions).

Also note that as with the previous action map entry the WebTable object name will come from the table property of the object map entry: &table& and the column number from the column property: &column&

Lastly note that the curr_row variable set in the first action is passed in as a parameter in the second action. So the steps in our subtest as follows:

UserIdCol

DOBCol

 

action

data

action

data

find

j.smith@testing.com

Val

03/12/1970

 

Will result in the following code (intentionally I haven’t shown the Axe error handling code):

curr_row = Browser("Browser").Page("UserDetails").WebTable("UserTable").GetRowWithCellText("j.smith@testing.com",1)

value = Browser("Browser").Page("UserDetails").WebTable("UserTable").GetCellData(curr_row,5)

rc = AxeMainAPI.StepValidateEqual("03/12/1970", value)

 

You can see that in this case the code flows logically passing the right values into the subsequent steps. When the test is run the results will appear as follows:

Selecting Rows by Positional Values

 

It would be easy to extend the support to select a row by its position in the table, so we can create custom actions to do so:

To select a row by passing a parameter:

class

action

Command

WebTableColumn

set.row(rownum)

curr_row = %PARAM1%

 

In this instance the Header counts as a row, so this can then be used in subtests in the following fashion e.g. to select row 4 and validate the DOB:

UserIdCol

DOBCol

 

action

data

action

data

Set.row(4)

 

Val

22/02/1984

 

We could also use the technique to find the last row in the table with a custom action:

class

action

Command

WebTableColumn

set.lastrow

curr_row = %REFERENCE%WebTable("&table&").RowCount

 

In this instance the action sets the variable curr_row to the RowCount for the table, essentially setting it to the last available row, again used in subtests as follows:

UserIdCol

DOBCol

 

action

data

action

data

Set.lastrow

 

Val

22/02/1984

 

 

Web Table Columns with Embedded Objects

Often WebTables are not just used to present information, they can also be used to embed other objects, for example Checkboxes for selecting items, buttons for ongoing navigation and links. Extending the techniques above allows us to deal with these in a consistent way.

The table in our example above now contains a column of checkboxes:

How can we work with this column in a consistent way? Ideally we would want to use the column in the subtest as follows, e.g. to find j.smith@testing.com and select the checkbox in that row:

UserIdCol

SelectCol

 

action

data

action        

data

find

j.smith@testing.com

set

ON

Through the use of additional custom classes we can define the type of column that is being worked with, for our example above we will define a WebTableCheckBoxColumn in our object map as Column 6:

name

class

table

column

UserDetails.UserIdCol

WebTableColumn

UserTable

1

UserDetails.TitleCol

WebTableColumn

UserTable

2

UserDetails.NameCol

WebTableColumn

UserTable

3

UserDetails.GenderCol

WebTableColumn

UserTable

4

UserDetails.DOBCol

WebTableColumn

UserTable

5

UserDetails.SelectCol

WebTableCheckBoxColumn

UserTable

6

We then need to implement the Set action for this new class.

QTP allows us to retrieve a reference to the child item of a cell within a WebTable using the ChildItem method, this requires the child object type in this case WebCheckBox.

So to Implement the set action for this column type the following can be used:

class

action

Command

WebTableCheckBoxColumn

set

%REFERENCE%WebTable("&table&").ChildItem(curr_row,&column&,”WebCheckBox”,0).Set “%DATA%”

In the case of a column with a Button or a Link, the same technique could be adapted, here are examples of action map entries for Columns with those object types embedded :

class

action

Command

WebTableButtonColumn

set

%REFERENCE%WebTable("&table&").ChildItem(curr_row,&column&,”WebButton”,0).Click

WebTableLinkColumn

set

%REFERENCE%WebTable("&table&").ChildItem(curr_row,&column&,”Link”,0).Click

 

Summary

In conclusion, we have combined a number of techniques, Custom Object Classes, A new Custom Action and breaking a complex activity into multiple steps to solve interaction with the Table. This can be built upon for more complex tables.

The technique could also be extended to non-web tables where functions would be required to find the item in a specific column.