Automated GUI Testing
by George Nistorica
|
Pages: 1, 2, 3, 4
The syntax for FindWindowLike is:
FindWindowLike($window,$titleregex,$classregex,$childid,
$maxlevel).
It returns a list of found windows. The parameters are:
$windowThis is the (numeric) handle of the parent window to search under (remember the hierarchical organization of windows in a GUI). You may use undef in order to search for all windows.
$window should be a decimal value, so if you know the window's hex handle (as displayed by WinSpy++) you need to convert it.
$titleregexThis is the most often used parameter. It is a regular expression for
FindWindowLiketo match against window titles to find the appropriate window(s).$classregexThis matches against a window class. Suppose that you want to find all buttons in an application. Use the function like this:
my @windows = FindWindowLike(undef,"","Button");
Currently theNote:if you don't care what the class of the window is, do not omit the$classregexparameter. Instead, use an empty string.FindWindowLike()function does not check if$classregexis undefined, so you will end up with a lot of Perl warnings.$childidIf you pass this argument, then the function will match all windows with this ID.
$maxlevelMaximum depth level to match windows.
As you may have noticed, the tested program has a title that
matches the string "Tested". Thus, the tester starts by searching
windows matching this title:
@windows = FindWindowLike( undef, "Tested", "" );
@windows will contain a list of window IDs that have a title
matching the string. The point here is that you probably don't want the
tested program to start more than once simultaneously.
if ( @windows > 1 ) {
print "* The \"tested\" program is started more than once!\n";
...
}
If there is no tested application already running, the program
can start it and repeat the procedure, searching for windows that match our
criteria (they contain the string "Tested" in their titles). If it's running just
once, its ID is $windows[0]. In fact, this is the root window of
the application.
There's no point in going further with the program if the GUI hasn't started, so the code checks this:
unless ( @windows ) {
print "* The program hasn't started!\n";
exit 1;
}
Setting a Specific Window to Foreground
Finding a window is sometimes not enough. Often, you need to send some input
to the window. Obviously, the window should be in the foreground. The
appropriate functions are SetActiveWindow() and
SetForegroundWindow().
Because of the way windows work under Win32, this may be trickier than it
seems. Basically, if the caller is not in the foreground, it can not give
another window "focus." MSDN explains this in the documentation of the SetForegroundWindow
and SetActiveWindow
functions.
While this behavior is easy to explain if you consider that you usually don't want applications that run in background to be able to annoy you (at least) by grabbing focus, there is at least one drawback. If you are running a GUI (perhaps remotely) to which you will send sensitive input for some reason, you may send those secrets to another, possibly malicious, application if the tested application does not have focus!
Another problem is in running tester programs remotely, or at regular intervals. Suppose that your tester program spawns the tested program, then starts sending it events (mouse events and/or keystrokes). If the computer is in a "locked" state, according to Microsoft documentation, no application can be in the foreground. You may have unexpected results.
If the GUI you are automating receives sensitive input (such as passwords), you have to find a means to "isolate" that machine's input/output devices, such as keyboard/mouse/monitor, so that no one unauthorized can peek at what your Perl program is typing in. Good luck.
In my opinion, every time you send input to a GUI, the Win32::GuiTest program should check if the application is in the foreground. If it isn't, it should try to bring it to the front. If it can't do that, it should fail and not continue.

