Simple technique to test drive a browser application

A while ago, I needed to do some profiling of a complex wizard-type ASP.NET application. I needed a script to drive a reproducible path through the application so I could compare the effect of code changes from run to run. Filling in each form was tedious and error prone. ACT would have probably done the trick, but the application utilized lots of hidden fields, viewstate, and Server.Transfers that made writing an ACT test difficult. I was in search of a quick and dirty, low-tech solution.

The solution I arrived at after some trial and error was to simply write a JScript script that uses SendKeys to emulate a user banging away at the keyboard. If you can drive your application from the keyboard through a sequence of characters, tabs, arrows, enter keys etc, this technique may be useful to you. In addition to profiling, developers found this technique useful to drive through a set of prerequisite forms to get down to the screens they were working on more quickly.

The trick was to use the Internet Explorer events to prevent overdriving the app by sending the keys too early. Trapping the DocumentComplete event allows the script wait until the page has completely downloaded before sending the next keystrokes.

Here is a simplified version of the script. You can get much fancier by passing in parameters such as initial URL and username/password, allowing to switch between multiple test cases, and logging page timings. Using something like “ie.Document.frames.item(0).document.all["Busy"]”, you can even walk into the document object model of the displayed page to do things like sense error conditions and branch your test accordingly.

var gShell = new ActiveXObject("Wscript.Shell");
var isOperationComplete = false;
var navigateCount = 0;
var currentUrl = "";

// Create Internet Explorer and wire up its events
var ie = WScript.CreateObject("InternetExplorer.Application","ie_");
ie.Visible = true;
gShell.AppActivate("Microsoft Internet Explorer");

////////////////////////////////////
// Test script

ie.Navigate("http://localhost/WebApplication1/Default.aspx");
Wait();

// Enter the user name
// tab to password field and enter password
// then press enter (~)

Go("username{TAB}password~");

// etc...
Go("field1{TAB}field2{TAB}{DOWN}{TAB}~");

// Close the browser by sending Alt-F4
gShell.SendKeys("%{F4}");

////////////////////////////////////
// Utilities

function Go(keys) {
    gShell.SendKeys(keys);
    Wait();
}

function Wait() {
    isOperationComplete = false;
    var start = new Date();
    while (!isOperationComplete) {
        WScript.Sleep(100);
    }
    var end = new Date();
    isOperationComplete = false;
    return (end-start);
}

////////////////////////////////////
// Internet Explorer Event Handlers

function ie_NavigateComplete2(ie, url) {
    navigateCount++;
}

function ie_DocumentComplete(ie, url) {
    navigateCount--;
    if (navigateCount <= 0) {
        currentUrl = url;
        navigateCount = 0;
        isOperationComplete = true;
    }
}

function ie_OnQuit() {
    WScript.Quit(1);
}

 

 

3 Comments

  • You can do almost the same thing in NUnitAsp, and it seems like it would be more resistant to change. If the page you were testing was redesigned and things moved around, it would probably break. NUnitAsp avoids this by interacting with the named control, so the page can be totally rearranged and still work with the original test.

  • Thanks Darrell, I need to learn more about NUnitASP. I've had a shortcut to the Server Side article about it on my desktop now for a couple weeks...you know how that goes.



    You definitely pointed out one of the shortcomings with the SendKeys approach, it is fragile. If tab order changes, things can get out of whack in a hurry.



    After I made the post I realized that I forgot to mention another side-effect of doing it this way...the app relies heavily on client-side scripting. ACT, LoadRunner (and I'm guessing NUnitASP) etc, all reproduce the server side of things. The only way to really run both client and server sides of the app was to actually run it in a real-live Internet Explorer.



    Believe me, I'm not going to defend this as the best or only way to do it, but I just wanted to get it out there in case it saves someone some time. For a low-tech quick and dirty solution, it's surprising how well it worked for us.

  • Actually, instead of using gShell.Send, you can directly access and modify the elements on the web page loaded in your Internet explorer object.

    For example if you had a text box with an id of oUsernamebox you could modify it from the JScript file by using ie.document.all.oUsernamebox.value = &quot;username&quot;

    . Like your script, this does require client side scripting.

Comments have been disabled for this content.