Complex dynamic web pages may take a few seconds to load, and the web page scripts can also load additional content after the page has been loaded. As a result, the web page load time may be longer during test playback than during recording. To avoid test failures due to timing issues, you can make your tests wait until a web page or element is completely loaded.
This topic describes various approaches to waiting for web pages.
Waiting for Web Pages in Scripts
In scripts, you can wait until a web page is loaded completely using the following approaches:
Waiting for a Test Object to Appear
The WaitPage
method lets you pause the test execution until the Page
object that contains the specified URL becomes accessible or until the specified time period elapses. Note that the method does not wait until a web page is loaded completely, it only waits for the corresponding Page
object and returns the object as the result.
You can use the Exists
property to determine whether a new page has been loaded successfully (see below).
Using Hard-Coded Delays
To wait until a web page is loaded completely, you can use the Wait
or ToUrl
method. The Wait
method returns the page's URL, frame or resource that was loaded last. On a failure, the method returns an empty string. The ToUrl
method returns the Page
object that corresponds to the newly loaded web page.
You can specify the waiting timeout for the Wait
and ToUrl
methods using their WaitTime parameter. If the parameter is specified, the script execution is paused until the browser loads the page and becomes ready to accept user input or until the specified timeout is reached. If the parameter is omitted or equal to -1, the waiting timeout is specified by the project's Web page loading timeout option.
The Wait
and ToUrl
methods check whether the loading process has been finished and the next test command is executed after the specified page has been loaded completely. This works for simple pages and is acceptable in most situations. However, for complex (especially dynamic) pages these methods may return a value earlier than the page is loaded completely.
The issue is that the process may report that the page has been loaded, while some elements of the page are still being loaded or created. This happens, for instance, when the page contains frames or script code that performs additional processing upon loading the page. To wait until a page is loaded, you can call the aqUtils.Delay
method after instructing the browser to navigate to the page:
JavaScript, JScript
function useDelay()
{
var page;
// Run Internet Explorer and open a page
Browsers.Item(btIExplorer).Run("http://smartbear.com/");
// Wait for 10 seconds until the page is loaded
aqUtils.Delay(10000);
// Get a page object
page = Sys.Browser().Page("*");
...
}
Python
def useDelay():
# Run Internet Explorer and open a page
Browsers.Item[btIExplorer].Run("http://smartbear.com/");
# Wait for 10 seconds until the page is loaded
aqUtils.Delay(10000);
# Get a page object
page = Sys.Browser().Page("*");
# ...
VBScript
Sub useDelay
Dim page
' Run Internet Explorer and open a page
Browsers.Item(btIExplorer).Run("http://smartbear.com/")
' Wait for 10 seconds until the page is loaded
aqUtils.Delay 10000
' Get a page object
Set page = Sys.Browser.Page("*")
...
End Sub
DelphiScript
procedure useDelay();
var page : OleVariant;
begin
// Run Internet Explorer and open a page
Browsers.Item[btIExplorer].Run('http://smartbear.com/');
// Wait for 10 seconds until the page is loaded
aqUtils.Delay(10000);
// Get a page object
page := Sys.Browser.Page('*');
...
end;
C++Script, C#Script
function useDelay()
{
var page;
// Run Internet Explorer and open a page
Browsers["Item"](btIExplorer)["Run"]("http://smartbear.com/");
// Wait for 10 seconds until the page is loaded
aqUtils["Delay"](10000);
// Get a page object
page = Sys["Browser"]()["Page"]("*");
...
}
Note, however, that using hard-coded delays has a few disadvantages. For example, the test will be paused even if the page is already loaded. Also, the test might fail if the web page has not been loaded during the delay.
Checking if a Page Is Fully Loaded
To ensure that a web page has been loaded, you can wait until the “problematic” elements are loaded.
For instance, if you are testing a page with frames, you can wait until the page obtains the collection of frames and then use the contentDocument.readyState
property of the frames to check whether their content is fully loaded.
Note: | Before you check the contentDocument.readyState property of the “problematic” elements, always make sure that the elements already exist on the page and they can be obtained as child objects of the corresponding page object in your tests. |
The following code demonstrates this approach:
JavaScript
function Main()
{
let URL = "http://smartbear.com/";
// Run Internet Explorer and open a page
Browsers.Item(btIExplorer).Run(URL);
let page = Sys.Browser().Page("*");
let stopTime = GetTickCount() + 10000;
while (GetTickCount() < stopTime)
{
frames = page.FindAllChildren("ObjectType", "Frame", 5, true);
if (frames.length > 0)
{
var waitFrame = false;
for (i in frames)
{
let frame = frames[i];
if (frame.Exists && (frame.contentDocument.readyState != "complete"))
{
waitFrame = true;
break;
}
}
if (! waitFrame)
break;
aqUtils.Delay(100);
}
}
}
JScript
function Main()
{
var URL = "http://smartbear.com/";
// Run Internet Explorer and open a page
Browsers.Item(btIExplorer).Run(URL);
var page = Sys.Browser().Page("*");
var stopTime = GetTickCount() + 10000;
while (GetTickCount() < stopTime)
{
frames = page.FindAllChildren("ObjectType", "Frame", 5, true).toArray();
if (frames.length > 0)
{
var waitFrame = false;
for (var i = 0; i < frames.length; i++)
{
var frame = frames[i];
if (frame.Exists && (frame.contentDocument.readyState != "complete"))
{
waitFrame = true;
break;
}
}
if (! waitFrame)
break;
aqUtils.Delay(100);
}
}
}
Python
def WaitPage():
URL = "http://smartbear.com/";
# Run Internet Explorer and open a page
Browsers.Item[btIExplorer].Run(URL);
page = Sys.Browser().Page("*");
stopTime = GetTickCount() + 10000;
while (GetTickCount() < stopTime):
frames = page.FindAllChildren("ObjectType", "Frame", 5, True);
if VarArrayHighBound(frames, 1) >= 0:
waitFrame = False;
for i in range (0, VarArrayHighBound(frames, 1)-1):
frame = frames[i];
if ((frame.Exists) and (frame.contentDocument.readyState != "complete")):
waitFrame = True;
break;
if not waitFrame:
break;
aqUtils.Delay(100);
VBScript
Sub Main
URL = "http://smartbear.com/"
' Run Internet Explorer and open a page
Browsers.Item(btIExplorer).Run(URL)
Set page = Sys.Browser().Page("*")
stopTime = GetTickCount() + 10000
Do While GetTickCount() < stopTime
frames = page.FindAllChildren("ObjectType", "Frame", 5, True)
If UBound(frames) >= 0 Then
waitFrame = False
For i = 0 To UBound(frames)
Set frame = frames(i)
If frame.Exists And frame.contentDocument.readyState <> "complete" Then
waitFrame = true
Exit For
End If
Next
If Not waitFrame Then
Exit Do
End If
aqUtils.Delay(100)
End If
Loop
End Sub
DelphiScript
procedure Main;
var
URL, page, stopTime, waitFrame, frames, frame, i : OleVariant;
begin
URL := 'http://smartbear.com/';
// Run Internet Explorer and open a page
Browsers.Item(btIExplorer).Run(URL);
page := Sys.Browser().Page('*');
stopTime := GetTickCount() + 10000;
while (GetTickCount() < stopTime) Do
begin
frames := page.FindAllChildren('ObjectType', 'Frame', 5, true);
if VarArrayHighBound(frames, 1) >= 0 then
begin
waitFrame := false;
for i := 0 to VarArrayHighBound(frames, 1) do
begin
frame := frames[i];
if ((frame.Exists) and (frame.contentDocument.readyState <> 'complete')) then
begin
waitFrame := true;
break;
end;
end;
if not waitFrame then
break;
aqUtils.Delay(100);
end;
end;
end;
C++Script, C#Script
function Main()
{
var URL = "http://smartbear.com/";
// Run Internet Explorer and open a page
Browsers["Item"](btIExplorer)["Run"](URL);
var page = Sys["Browser"]()["Page"]("*");
var stopTime = GetTickCount() + 10000;
while (GetTickCount() < stopTime)
{
frames = page["FindAllChildren"]("ObjectType", "Frame", 5, true)["toArray"]();
if (frames["length"] > 0)
{
var waitFrame = false;
for (var i = 0; i < frames["length"]; i++)
{
var frame = frames[i];
if (frame["Exists"] && (frame["contentDocument"]["readyState"] != "complete"))
{
waitFrame = true;
break;
}
}
if (! waitFrame)
break;
aqUtils["Delay"](100);
}
}
}
The general approach is to wait until the desired web page element becomes available or until it contains the correct values. For instance, if you know that the page script adds HTML tags at the end of the page or modifies text at the end of the page, you can create a test that will wait until the element is available (or until the content is changed). The following code snippets wait until the tested web page contains an element whose contentText
attribute equals TestComplete:
JavaScript, JScript
var page;
// Run Internet Explorer and open a page
Browsers.Item(btIExplorer).Run("http://smartbear.com/");
page = Sys.Browser().Page("*");
// Waiting for the object
do
{
aqUtils.Delay(100);
obj = page.NativeWebObject.Find("contentText", "TestComplete");
}
while (! obj.Exists)
...
Python
# Run Internet Explorer and open a page
Browsers.Item[btIExplorer].Run("http://smartbear.com/");
page = Sys.Browser().Page("*");
# Waiting for the object
while True:
aqUtils.Delay(100);
obj = page.NativeWebObject.Find("contentText", "TestComplete");
if obj.Exists:
break;
# ...
VBScript
Dim page
' Run Internet Explorer and open a page
Browsers.Item(btIExplorer).Run("http://smartbear.com/")
Set page = Sys.Browser.Page("*")
' Wait for the object
Do
aqUtils.Delay 100
Set obj = page.NativeWebObject.Find("contentText", "TestComplete")
Loop Until obj.Exists
...
DelphiScript
var page, obj : OleVariant;
begin
// Run Internet Explorer and open a page
Browsers.Item[btIExplorer].Run('http://smartbear.com/');
page := Sys.Browser.Page('*');
// Wait for the object
repeat
aqUtils.Delay(100);
obj := page.NativeWebObject.Find('contentText', 'TestComplete');
until obj.Exists;
...
end;
C++Script, C#Script
var page;
// Run Internet Explorer and open a page
Browsers["Item"](btIExplorer)["Run"]("http://smartbear.com/");
page = Sys["Browser"]()["Page"]("*");
// Waiting for the object
do
{
aqUtils["Delay"](100);
obj = page["NativeWebObject"]["Find"]("contentText", "TestComplete");
}
while (! obj["Exists"])
...
Waiting for Web Pages in Keyword Tests
To open a web page from keyword tests in TestComplete, you use the Navigate operation. The operation waits until the web page is downloaded completely for the period of time specified by its WaitTime parameter. If the parameter is omitted, the waiting time is specified by the project's Web page loading timeout option. However, the operation may report that the page has been loaded while it is still being loaded (for example, scripts of dynamic web pages may load additional content or modify the existing content after the page has been loaded).
To work around the problem you can specify an additional wait timeout using the Delay operation. This operation pauses your test for the specified time period.
You can also call any of the methods described above from your keyword tests. To do this, use the Call Object Method or Run Code Snippet operation. For a detailed description of how to call methods from your keyword tests, see the Calling Object Methods topic.
See Also
Testing Web Applications
Common Tasks for Web Testing
Finding Objects on Web Pages
Testing Dynamic Web Pages