FYI, my post to the JsUnit group.
-Dan
-unless you love someone-
-nothing else makes any sense-
e.e. cummings
---------- Forwarded message ----------
Date: Wed, 30 Nov 2005 15:06:56 -0800 (Pacific Standard Time)
From: Dan Fabulich <[EMAIL PROTECTED]>
Reply-To: [EMAIL PROTECTED]
To: [EMAIL PROTECTED]
Subject: [jsunit] AJAXUnit?
Since it looks like many people here have had to kludge in something to
test AJAX and other asynchronous JavaScript events, I thought I'd mention
one of my favorite solutions.
When you initiate an asynchronous call like window.setTimeout,
XMLHTTPRequest.send, or change location.href, what you'd want to do is
something like this:
function testFoo() {
myrequest.send();
while (myrequest.readyState < 4) {
failIfTimedOut();
sleep(10);
}
assertEquals(200, myrequest.status);
}
Unfortunately, you can't actually write the test this way, because
JavaScript has no native sleep() function. You can register a callback
function with XMLHttpRequest's onReadyStateChange field, but even if your
code does get called back, it will be too late for testFoo, which will
return immediately unless it can somehow find a way to wait for the
callback.
JavaScript has no native sleep() function, but Java does. It's really
easy to expose this as an applet:
import java.applet.Applet;
public class Sleeper extends Applet {
public void sleep(long millis) throws InterruptedException {
Thread.sleep(millis);
}
}
Put this applet in your HTML page like this:
<APPLET CODE="Sleeper" WIDTH=0 HEIGHT=0 NAME="sleeper" ID="sleeper">
</APPLET>
Then you can invoke document.sleeper.sleep(500) to synchronously sleep.
That allows you to, for example, register event handlers that do nothing
but set a flag declaring that the event is done. You can use this to
synchronously sleep-and-poll those flags until your asynchronous events
appear to be done, and then take action afterwards.
I should point out that I couldn't get this to work in Internet Explorer
6.0 on XP SP2; the only way I found to do it was to write an ActiveX
control that did the same thing in C#.
// Sleeper.cs
using System;
using System.Threading;
using System.Runtime.InteropServices;
namespace kludge
{
[ClassInterface(ClassInterfaceType.AutoDual)]
public class Sleeper
{
public void sleep(int milliSeconds)
{
Thread.Sleep(milliSeconds);
}
}
}
Then you can use the .NET Framework to compile it (no VS.NET required)
csc /t:library Sleeper.cs
regasm Sleeper.dll /tlb:SleeperNet.dll /codebase
and finally load it up in your JavaScript with:
var IESleeper = new ActiveXObject("kludge.Sleeper");
IESleeper.sleep(500);
It seems to me that the only other way to handle this problem is to make
JsUnit itself more friendly to asynchronous events throughout the test
lifecycle. The most natural way I can see to accomplish this is to make a
special JsUnit-based setTimeout() method; if you call the JsUnit
setTimeout() in a test, JsUnit would invoke your code in a try-block, and
handle any errors/failures.
The problem with this, as I'd mentioned in my earlier post, is that it
means that everything has to be broken into parts... it's like setUpPage
vs. setUpPageComplete, but *everywhere*. Your tests will have to start
keeping track: is this the first time I'm being invoked? If so, open the
window. Or is it the second time? In that case, do XYZ. Is this the
third time I'm being invoked...? Writing good tests like this is really
hard, basically because writing asynchronous code is hard.
Anyway, perhaps either or both of these should become an official part of
the JsUnit framework? The world cries out for AJAXUnit.
-Dan
_______________________________________________
Selenium-users mailing list
Selenium-users@lists.public.thoughtworks.org
http://lists.public.thoughtworks.org/mailman/listinfo/selenium-users