Handling unexpected active Windows
A common problem in GUI testing is the appearance of an unexpected active window -- for example, a warning message box in an HTML browser. This topic describes how to handle this problem.
Imagine that you record a click action on a secure page, and this link takes you to a page that is not secure. Assume your browser's security setting is adjusted to cause a message box to appear, warning you that the next page will not be secure. You click OK to dismiss the warning message, and then you click a checkbox on the page that is not secure. The recorded Functional Test script would look something like this:
linkThatLeavesSecurePage().click();
Dialog_HtmlDialogButtonOK().click();
CheckboxOnTheUnsecurePage().click();
When you play the script back against a browser with a different
security setting, the script does not play back because the Dialog_HtmlDialogButtonOK()
cannot
be found. You can comment out the Dialog_HtmlDialogButtonOK().click();
statement,
but you will have failures when the dialog does show up.
One solution is to wait for the message to appear. If it does not appear, you can continue. The solution can be achieved with the following code:
linkThatLeavesSecurePage().click();
try
{
Dialog_HtmlDialogButtonOK().click();
}
catch(ObjectNotFoundException e) {}
CheckboxOnTheUnsecurePage().click();
This code accomplishes your primary goal. If the warning message appears, you dismiss it. If it does not appear, you eventually stop waiting and then continue. However, you may not want to wait the default amount of time for the warning message to show up. If you are sure that when the warning message does show up it will arrive within 5 seconds, you can speed this up by coding as follows:
linkThatLeavesSecurePage().click();
try
{
Dialog_HtmlDialogButtonOK().waitForExistence(5,1);
Dialog_HtmlDialogButtonOK().click();
}
catch(ObjectNotFoundException e) {}
CheckboxOnTheUnsecurePage().click();
A reasonable objection to this approach is that you need to add
this special code wherever a link on a browser might switch pages
and cause a change in security. Handling this situation in a common
place without changing many test scripts would be more efficient.
By implementing the onObjectNotFound
exception you
can handle the event whenever it occurs. By putting the implementation
in a helper super script, you can handle the event for any Functional Test script that extends this helper super class.
The code in the following example implements a base class for scripts
that test HTML applications. This base class implements onObjectNotFound
.
The onObjectNotFound
method looks through all the
HTML domains and looks for any HTML dialog boxes. Every HTML dialog
box is dismissed by pressing Enter. If any dialog boxes are dismissed,
the TestObject
method is restarted. If no dialog
boxes are dismissed, the method does nothing, and the ObjectNotFoundException
is
thrown as usual.
import com.rational.test.ft.script.*;
import com.rational.test.ft.object.interfaces.*;
/**
* This class provides some base capabilities for working
* with HTML.
*/
public abstract class HtmlScript extends RationalTestScript
{
/**
* Overrides the base implementation of onObjectNotFound. Whenever
* this event occurs, look through all the active domains (places
* where objects might be found). For HTML domains (Java
* and other domains are skipped) finds all the top objects.
* If the top object is an Html Dialog,
* types an Enter key to dismiss the dialog.
* Logs a warning when this happens.
*/
public void onObjectNotFound(ITestObjectMethodState testObjectMethodState)
{
boolean dismissedAWindow = false;
DomainTestObject domains[] = getDomains();
for (int i = 0; i < domains.length; ++i)
{
if (domains[i].getName().equals("Html"))
{
// HTML domain is found.
TestObject[] topObjects = domains[i].getTopObjects();
if (topObjects != null)
{
try
{
for (int j = 0; j < topObjects.length; ++j)
{
if (topObjects[j].getProperty(".class").equals("Html.Dialog"))
{
// A top-level HtmlDialog is found.
logWarning("HtmlScript.onObjectNotFound - dismissing dialog.");
try
{
dismissedAWindow = true;
((TopLevelTestObject)topObjects[j]).inputKeys("{enter}");
}
catch(RuntimeException e) {}
}
}
}
finally
{
//unregister all references to top objects
unregister(topObjects);
}
}
}
}
if (dismissedAWindow)
{
// try again
testObjectMethodState.findObjectAgain();
}
else
{
logWarning("HtmlScript.onObjectNotFound; no Html Dialog to dismiss");
}
}
}
Note that the above implementation of HtmlScript
is
only suitable for testing HTML. You may want to be able to use this
base class for any script, including scripts testing Java™. In this case, you must make sure that
the TestObject
is a Rational® Functional Tester HTMLobject
before
dismissing the HTML dialog boxes. You can add the following code to
the beginning of the onObjectNotFound
method:
if (!testObjectMethodState.getTestObject().
getPropertyFromMap(IMapPropertyName.DOMAIN).equals("Html"))
{
return;
}