TestComplete provides scripting access to web page elements as well as to their attributes, methods and events. You can use this functionality to obtain data from tables displayed on the web page under test.
A table is an HTML TABLE element with special sub-elements for the table’s header, footer and body. These sub-elements contain rows and cells.
To retrieve data from a table, you can use the “native” properties of the DOM table
object. Alternatively, if you use the Tree web testing model, you can work with HTML tables using the features provided by this model.
Using Internal Properties
To retrieve data from a table, you can use the rows
and cells
properties of the table
object (this is an object defined by the Document Object Model). The cells
property belongs both to the table
and to the row
objects. The table’s property provides access to all cells of the table. The row’s property provides access to values displayed in the row’s cells.
The code below goes through the rows and cells of a table and posts the cell contents to the log. The sample routine works with the www.w3schools.com/html/tryit.asp?filename=tryhtml_table_intro web page displaying a sample table.
JavaScript, JScript
function SimpleParsing()
{
var url = "https://www.w3schools.com/html/tryit.asp?filename=tryhtml_table_intro";
Browsers.Item(btIExplorer).Run(url);
var page = Sys.Browser("*").Page("*");
var table = page.FindChild("tagName", "table", 10);
if (table.Exists)
{
// Goes through the rows and cells of the table
for (var i = 0; i < table.rows.length; i++)
{
Log.AppendFolder("Row " + i);
for (var j = 0; j < table.rows.item(i).cells.length; j++)
Log.Message("Cell " + j + ": " + table.rows.item(i).cells.item(j).innerText);
Log.PopLogFolder();
}
}
else
Log.Warning("The table was not found");
}
Python
def SimpleParsing():
url = "https://www.w3schools.com/html/tryit.asp?filename=tryhtml_table_intro";
Browsers.Item[btIExplorer].Run(url);
page = Sys.Browser("*").Page("*");
table = page.FindChild("tagName", "table", 10);
if table.Exists:
# Goes through the rows and cells of the table
for i in range (0, table.rows.length):
Log.AppendFolder("Row " + IntToStr(i));
for j in range (0, table.rows.item(i).cells.length):
Log.Message("Cell " + IntToStr(j) + ": " + table.rows.item(i).cells.item(j).innerText);
Log.PopLogFolder();
else:
Log.Warning("The table was not found");
VBScript
Sub SimpleParsing
Dim page, table
url = "https://www.w3schools.com/html/tryit.asp?filename=tryhtml_table_intro"
Browsers.Item(btIExplorer).Run url
Set page = Sys.Browser("*").Page("*")
Set table = page.FindChild("tagName", "table", 10)
If table.Exists Then
' Goes through the rows and cells of the table
For i = 0 To table.rows.length - 1
Log.AppendFolder("Row " & i)
For j = 0 To table.rows.item(i).cells.length - 1
Log.Message("Cell " & j & ": " & table.rows.item(i).cells.item(j).innerText)
Next
Log.PopLogFolder
Next
Else
Log.Warning("The table was not found")
End If
End Sub
DelphiScript
procedure SimpleParsing();
var url, page, table, i, j;
begin
url := 'https://www.w3schools.com/html/tryit.asp?filename=tryhtml_table_intro';
Browsers.Item(btIExplorer).Run(url);
page := Sys.Browser('*').Page('*');
table := page.FindChild('tagName', 'table', 10);
if table.Exists then
begin
// Goes through the rows and cells of the table
for i := 0 to table.rows.length - 1 do
begin
Log.AppendFolder('Row ' + aqConvert.VarToStr(i));
for j := 0 to table.rows.item(i).cells.length - 1 do
Log.Message('Cell ' + aqConvert.VarToStr(j) + ': ' + table.rows.item(i).cells.item(j).innerText);
Log.PopLogFolder();
end;
end
else
Log.Warning('The table was not found');
end;
C++Script, C#Script
function SimpleParsing()
{
var url = "https://www.w3schools.com/html/tryit.asp?filename=tryhtml_table_intro";
Browsers["Item"](btIExplorer)["Run"](url);
var page = Sys["Browser"]("*")["Page"]("*");
var table = page["FindChild"]("tagName", "table", 10);
if (table["Exists"])
{
// Goes through the rows and cells of the table
for (var i = 0; i < table["rows"]["length"]; i++)
{
Log["AppendFolder"]("Row " + i);
for (var j = 0; j < table["rows"]["item"](i)["cells"]["length"]; j++)
Log["Message"]("Cell " + j + ": " + table["rows"]["item"](i)["cells"]["item"](j)["innerText"]);
Log["PopLogFolder"]();
}
}
else
Log["Warning"]("The table was not found");
}
Note that the rows
property of the table
object provides access to all rows of the table, including the rows displayed in the table’s header and footer. To only process cells of the table body, you obtain the objects corresponding to the TBODY elements (note that a table can contain several TBODY elements) and then go through the rows and cells of each TBODY.
The following code demonstrates how you can do this.
JavaScript, JScript
function Main()
{
var url = "https://www.w3schools.com/html/tryit.asp?filename=tryhtml_table_intro";
Browsers.Item(btIExplorer).Run(url);
var page = Sys.Browser("*").Page("*");
var table = page.FindChild("tagName", "table", 10);
if (table.Exists)
// Parses the table
ParseTable(table);
else
Log.Warning("The table is not found.");
}
function ParseTable(ATable)
{
Log.AppendFolder("Table");
// Parses the TBODY elements
for (var i = 0; i < ATable.tBodies.length; i++)
{
Log.AppendFolder("TBody " + i);
ParseTableBody(ATable.tBodies.item(i));
Log.PopLogFolder();
}
Log.PopLogFolder();
}
// Parses TBODY
function ParseTableBody(ABody)
{
// Goes through rows
for (var i = 0; i < ABody.rows.length; i++)
{
// Obtains a row
var row = ABody.rows.item(i);
Log.AppendFolder("Row " + i);
// Goes through cells
for (var j = 0; j < row.cells.length; j++)
{
// Obtains a cell
var cell = row.cells.item(j);
// Posts the cell's text to the log
Log.Message("Cell " + j + ": " + cell.innerText);
}
Log.PopLogFolder();
}
}
Python
def Main():
url = "https://www.w3schools.com/html/tryit.asp?filename=tryhtml_table_intro";
Browsers.Item[btIExplorer].Run(url);
page = Sys.Browser("*").Page("*");
table = page.FindChild("tagName", "table", 10);
if (table.Exists):
# Parses the table
ParseTable(table);
else:
Log.Warning("The table is not found.");
def ParseTable(ATable):
Log.AppendFolder("Table");
# Parses the TBODY elements
for i in range (0, ATable.tBodies.length):
Log.AppendFolder("TBody " + IntToStr(i));
ParseTableBody(ATable.tBodies.item(i));
Log.PopLogFolder();
Log.PopLogFolder();
# Parses TBODY
def ParseTableBody(ABody):
# Goes through rows
for i in range (0, ABody.rows.length):
# Obtains a row
row = ABody.rows.item(i);
Log.AppendFolder("Row " + IntToStr(i));
# Goes through cells
for j in range (0, row.cells.length):
# Obtains a cell
cell = row.cells.item(j);
# Posts the cell's text to the log
Log.Message("Cell " + IntToStr(j) + ": " + cell.innerText);
Log.PopLogFolder();
VBScript
Sub Main
Dim page, table
url = "https://www.w3schools.com/html/tryit.asp?filename=tryhtml_table_intro"
Browsers.Item(btIExplorer).Run url
Set page = Sys.Browser("*").Page("*")
Set table = page.FindChild("tagName", "table", 10)
If table.Exists Then
' Parses the table
ParseTable(table)
Else
Log.Warning("The table was not found.")
End If
End Sub
Sub ParseTable(ATable)
Dim i
Log.AppendFolder("Table")
' Parses the TBODY elements
For i = 0 To ATable.tBodies.length - 1
Log.AppendFolder("TBody " & i)
ParseTableBody(ATable.tBodies.item(i))
Log.PopLogFolder
Next
Log.PopLogFolder
End Sub
' Parses TBODY
Sub ParseTableBody(ABody)
Dim i, j, row, cell
' Goes through rows
For i = 0 To ABody.rows.length - 1
' Obtains a row
Set row = ABody.rows.item(i)
Log.AppendFolder("Row " & i)
' Goes through cells
For j = 0 To row.cells.length - 1
' Obtains a cell
Set cell = row.cells.item(j)
' Posts the cell's text to the log
Log.Message("Cell " & j & ": " & cell.innerText)
Next
Log.PopLogFolder()
Next
End Sub
DelphiScript
// Forward declarations
procedure ParseTable(ATable); forward;
procedure ParseTableBody(ABody); forward;
procedure Main();
var url, page, table;
begin
url := 'https://www.w3schools.com/html/tryit.asp?filename=tryhtml_table_intro';
Browsers.Item(btIExplorer).Run(url);
page := Sys.Browser('*').Page('*');
table := page.FindChild('tagName', 'table', 10);
if table.Exists then
// Parses the table
ParseTable(table)
else
Log.Warning('The table was not found.');
end;
procedure ParseTable(ATable);
var i;
begin
Log.AppendFolder('Table');
// Parses the TBODY elements
for i := 0 to ATable.tBodies.length - 1 do
begin
Log.AppendFolder('TBody ' + aqConvert.VarToStr(i));
ParseTableBody(ATable.tBodies.item[i]);
Log.PopLogFolder;
end;
Log.PopLogFolder;
end;
// Parses TBODY
procedure ParseTableBody(ABody);
var i, j, row, cell;
begin
// Goes through rows
for i := 0 to ABody.rows.length - 1 do
begin
// Obtains a row
row := ABody.rows.item[i];
Log.AppendFolder('Row ' + aqConvert.VarToStr(i));
// Goes through cells
for j := 0 to row.cells.length - 1 do
begin
// Obtains a cell
cell := row.cells.item[j];
// Posts the cell's text to the log
Log.Message('Cell ' + aqConvert.VarToStr(j) + ': ' + cell.innerText);
end;
Log.PopLogFolder;
end;
end;
C++Script, C#Script
function Main()
{
var url = "https://www.w3schools.com/html/tryit.asp?filename=tryhtml_table_intro";
Browsers["Item"](btIExplorer)["Run"](url);
var page = Sys["Browser"]("*")["Page"]("*");
var table = page["FindChild"]("tagName", "table", 10);
if (table["Exists"])
// Parses the table
ParseTable(table);
else
Log["Warning"]("The table was not found.");
}
function ParseTable(ATable)
{
Log["AppendFolder"]("Table");
// Parses the TBODY elements
for (var i = 0; i < ATable["tBodies"]["length"]; i++)
{
Log["AppendFolder"]("TBody " + i);
ParseTableBody(ATable["tBodies"]["item"](i));
Log["PopLogFolder"]();
}
Log["PopLogFolder"]();
}
// Parses TBODY
function ParseTableBody(ABody)
{
// Goes through rows
for (var i = 0; i < ABody["rows"]["length"]; i++)
{
// Obtains a row
var row = ABody["rows"]["item"](i);
Log["AppendFolder"]("Row " + i);
// Goes through cells
for (var j = 0; j < row["cells"]["length"]; j++)
{
// Obtains a cell
var cell = row["cells"]["item"](j);
// Posts the cell's text to the log
Log["Message"]("Cell " + j + ": " + cell["innerText"]);
}
Log["PopLogFolder"]();
}
}
Using Properties Provided by the Tree Model
If the Tree model is used in the current project, TestComplete reflects the actual hierarchy of objects on the HTML page under test in the web object tree. In this model, a table
object has child Cell
objects that correspond to the table cells. Cells are addressed using their zero-based row and column indexes. For instance, the Cell(2, 1)
notation corresponds to the second cell in the third row. Besides that, TestComplete extends the functionality of the DOM table
object with the RowCount
and ColumnCount(RowIndex)
properties. The RowCount
property returns the number of table rows, and the ColumnCount
property lets you get the number of cells in the row with the RowIndex index (in general, different table rows can contain a different number of cells). You can use these properties for iterating through the table cells.
Below is an example that processes a table using the described approach.
JavaScript, JScript
function Test()
{
switch (Options.Web.TreeModel)
{
case "DOM":
case "Tag":
Log.Warning("This example requires the Tree or Hybrid model. Setting the model to Tree.");
Options.Web.TreeModel = "Tree";
break;
}
var url = "https://www.w3schools.com/html/tryit.asp?filename=tryhtml_table_intro";
Browsers.Item(btIExplorer).Run(url);
var page = Sys.Browser("*").Page("*");
var table = page.FindChild("tagName", "table", 10);
// Parses the table
ParseTreeTable(table);
}
function ParseTreeTable(ATable)
{
Log.AppendFolder("Table");
for (var i = 0; i < ATable.RowCount; i++)
{
Log.AppendFolder("Row " + i);
// Goes through cells
for (var j = 0; j < ATable.ColumnCount(i); j++)
{
// Obtains a cell
var cell = ATable.Cell(i, j);
// Posts the cell's text to the log
Log.Message("Cell " + j + ": " + cell.innerText);
}
Log.PopLogFolder();
}
Log.PopLogFolder();
}
Python
def Test():
if (Options.Web.TreeModel == "DOM" or
Options.Web.TreeModel == "Tag"):
Log.Warning("This example requires the Tree or Hybrid model. Setting the model to Tree.");
Options.Web.TreeModel = "Tree";
url = "https://www.w3schools.com/html/tryit.asp?filename=tryhtml_table_intro";
Browsers.Item[btIExplorer].Run(url);
page = Sys.Browser("*").Page("*");
table = page.FindChild("tagName", "table", 10);
# Parses the table
ParseTreeTable(table);
def ParseTreeTable(ATable):
Log.AppendFolder("Table");
for i in range (0, ATable.RowCount):
Log.AppendFolder("Row " + IntToStr(i));
# Goes through cells
for j in range (0, ATable.ColumnCount[i]):
# Obtains a cell
cell = ATable.Cell(i, j);
# Posts the cell's text to the log
Log.Message("Cell " + IntToStr(j) + ": " + cell.innerText);
Log.PopLogFolder();
Log.PopLogFolder();
VBScript
Sub Test()
Dim page, table
Select Case Options.Web.TreeModel
Case "DOM"
Log.Warning("This example requires the Tree or Hybrid model. Setting the model to Tree.")
Options.Web.TreeModel = "Tree"
Case "Tag"
Log.Warning("This example requires the Tree or Hybrid model. Setting the model to Tree.")
Options.Web.TreeModel = "Tree"
End Select
url = "https://www.w3schools.com/html/tryit.asp?filename=tryhtml_table_intro"
Browsers.Item(btIExplorer).Run url
Set page = Sys.Browser("*").Page("*")
Set table = page.FindChild("tagName", "table", 10)
' Parses the table
ParseTreeTable(table)
End Sub
Sub ParseTreeTable(ATable)
Dim i, j
Log.AppendFolder("Table")
For i = 0 To ATable.RowCount - 1
Log.AppendFolder("Row " & i)
' Goes through cells
For j = 0 To ATable.ColumnCount(i) - 1
' Obtains a cell
Set cell = ATable.Cell(i, j)
' Posts the cell's text to the log
Log.Message("Cell " & j & ": " & cell.innerText)
Next
Log.PopLogFolder()
Next
Log.PopLogFolder()
End Sub
DelphiScript
// Forward declaration
procedure ParseTreeTable(ATable); forward;
procedure Test();
var url, browser, page, table;
begin
case Options.Web.TreeModel of
'DOM':
begin
Log.Warning('This example requires the Tree or Hybrid model. Setting the model to Tree.');
Options.Web.TreeModel := 'Tree';
end;
'Tag':
begin
Log.Warning('This example requires the Tree or Hybrid model. Setting the model to Tree.');
Options.Web.TreeModel := 'Tree';
end;
end;
url := 'http://samples.msdn.microsoft.com/workshop/samples/author/tables/HTML_Table.htm';
Browsers.Item(btIExplorer).Run(url);
page := Sys.Browser('*').Page('*');
table := page.FindChild('tagName', 'table', 10);
// Parses the table
ParseTreeTable(table);
end;
procedure ParseTreeTable(ATable);
var i, j, cell;
begin
Log.AppendFolder('Table');
for i := 0 to ATable.RowCount - 1 do
begin
Log.AppendFolder('Row ' + aqConvert.VarToStr(i));
// Goes through cells
for j := 0 to ATable.ColumnCount(i)-1 do
begin
// Obtains a cell
cell := ATable.Cell(i, j);
// Posts the cell's text to the log
Log.Message('Cell ' + aqConvert.VarToStr(j) + ': ' + cell.innerText);
end;
Log.PopLogFolder;
end;
Log.PopLogFolder;
end;
C++Script, C#Script
function Test()
{
switch (Options.Web.TreeModel)
{
case "DOM":
case "Tag":
Log["Warning"]("This example requires the Tree or Hybrid model. Setting the model to Tree.");
Options["Web"]["TreeModel"] = "Tree";
break;
}
var url = "https://www.w3schools.com/html/tryit.asp?filename=tryhtml_table_intro";
Browsers["Item"](btIExplorer)["Run"](url);
var page = Sys["Browser"]("*")["Page"]("*");
var table = page["FindChild"]("tagName", "table", 10);
// Parses the table
ParseTreeTable(table);
}
function ParseTreeTable(ATable)
{
Log["AppendFolder"]("Table");
for (var i = 0; i < ATable["RowCount"]; i++)
{
Log["AppendFolder"]("Row " + i);
// Goes through cells
for (var j = 0; j < ATable["ColumnCount"](i); j++)
{
// Obtains a cell
var cell = ATable["Cell"](i, j);
// Posts the cell's text to the log
Log["Message"]("Cell " + j + ": " + cell["innerText"]);
}
Log["PopLogFolder"]();
}
Log["PopLogFolder"]();
}
Note, however, that the table’s child Cell
objects provide access to all table cells, including those displayed in the table header and footer. If you only need to process the table body cells, use the approach described in the previous section.
You can call the described script routines from keyword tests. To do this, use the Run Script Routine operation. Prepare the script code and then add the operation to your keyword test. TestComplete will display the Select Test dialog where you will be able to choose the desired routine.