1st WebTest screencast: Creating a first Webtest Project

The first WebTest screencast is now (in fact since 2 weeks) available online: Creating a first WebTest project

Content: (duration ~4 minutes)

  1. Download WebTest from http://webtest.canoo.com
  2. Check download and environment
  3. Create a new WebTest project
  4. Start the demo tests
  5. Browse automatically opened reports
  6. Look at the sources
  7. Look at the documentation

This is quite simple and probably not so interesting for experimented WebTest users (or maybe a bit as the features of the utility webtest.xml are quite new).

My colleague Tomi Schütz and I are working on other screencasts to show WebTest features. Stay tuned, the next one should be quite impressive.

Compute Fibonacci numbers with Google Calculator and WebTest

You’ve surely written programs to compute the Fibonacci numbers using different programming languages (if not or if you’ve forgotten, have a look at the Wikipedia article “Fibonacci number“). Nevertheless I’m quite sure that you’ve never seen the following method: it’s an idea of my colleague Tomi Schütz and it uses WebTest to drive Google Calculator (if you don’t know it, just search for instance something like “48 + 89” with Google).

The idea is quite simple:

  • start with the initial values F0 = 0 and F1 = 1
  • invoke Google to compute the sum of these values
  • extract the result from the html page, this is F2
  • invoke Google to compute F1 + F2

Expressed as a WebTest this looks like:

<webtest name="Fibonacci">

<invoke url="http://www.google.com/ncr" description="Go to Google (in English)"/>
<verifyTitle text="Google" />
<setInputField name="q" value="WebTest" />
<clickButton label="Google Search" description="dummy search to cope only with one kind of submit button in the repeat"/>
<storeProperty name="previous" value="0" description="F0"/>
<storeProperty name="current" value="1" description="F1"/>
<repeat startCount="2" endCount="10">

<setInputField name="q" value="#{previous} + #{current}" />
<clickButton label="Search" />
<storeProperty name="previous" value="#{current}"/>
<storeXPath xpath="substring-after(//tr[.//img[@src='/images/calc_img.gif']]/td[3]//b/text(), '= ')" property="current" description="Store Fibonacci #{count}"/> <!-- ugly XPath but it's Google's fault!-->

</repeat>
<verifyProperty name="current" value="55" description="10th Fibonacci number"/>

</webtest>
(sorry for the formatting, WordPress.com is not the best blog hoster for code examples)

Running this script you get results like this: WebTest Fibonacci – Test Results

Ok, it was just for fun because, even if WebTest and Google are very fast, computing the 10th number of the Fibonacci sequence involved getting 11 html response pages and took 2496 ms here!

FrOSCon 2007: WebTest session accepted (last minute)

Finally I will present “Automatisiertes Testen von Webapplikationen” at the next FrOSCon conference in Sankt Augustin (Germany) August 26th. A slot became free and I’ve accepted to make this presentation that was initially refused.

HtmlUnit 1.13 released

I wanted to write a few words about HtmlUnit-1.12 which we have released for one week and HtmlUnit-1.13 is already out!

In fact this is nearly the same (it contains some improvements as our committers and contributors have been very active in the last 7 days) but this release was needed due to a problem in the HtmlUnit-1.12 maven package. I don’t know if this is a bug of maven or if I made a mistake while packaging it but the jar and the sources/javadoc contained in the package are not in sync!

This (double) release represents a giant step in the JavaScript support development. The change log contains over 120 entries among other following points:

  • full support for JQuery (with JQuery unit tests integrated in HtmlUnit’s own unit tests)
  • support of event capturing and bubbling
  • set Referer header in requests
  • initial support for IE conditional compilation
  • improved JavaScript execution speed
  • AjaxController allowing re-synchronization of asynchron AJAX call
  • IncorrectnessListener to get notified of things that HtmlUnit cope with but that don’t respect standards.
  • workarounds for some Rhino bugs

These changes allow to widely support complex JavaScript libraries like JQuery, Prototype, DWR or GWT. These new features combined for instance with the execution speed, the ability to run headless and without external dependencies, the possibility to catch different kind of application problems (js errors, non respect of standards, …) make of HtmlUnit a first choice candidate to ensure the quality of your web application in a programmatic way.

Of course this release will be soon included in WebTest and will allow some new functionalities. Stay tuned.

Improve Rhino’s RegExp using Java’s java.util.regex

Mozilla Rhino doesn’t use the facilities of java.util.regex to implement regular expression support in JavaScript but provides own regular expression implementation. Sadly this implementation is both buggy (see bug 369860) and slow.

Bug with non capturing groups
Here is a variation of bug 369860 occurring in String.replace.

The regular expression used is really “real life” stuff as it is what the prototype library uses to filter scripts in the text of received XMLHttpRequest.


public void testBuggyReplace()
{
  final Context ctx = Context.enter();
  final ScriptableObject topScope = ctx.initStandardObjects();
  final String text = "<b>bla</b><script>alert(123);</script>bla";
  final String regex = "(?:<script.*?>)((\\n|\\r|.)*?)(?:<\\/script>)";
  final String expected = "<b>bla</b>bla";
  assertEquals(expected, text.replaceAll(regex, "")); // check replacement
  topScope.put("str", topScope, regex);
  topScope.put("text", topScope, text);
  topScope.put("expected", topScope, expected);
  final String script = "var re = new RegExp(str, 'img');\n"
    + "var s = text.replace(re, '');\n"
    + "if (s != expected)"
    + " throw 'Expected >' + expected + '' + s + '";
  ctx.evaluateString(topScope, script, "test", 0, null);
}

Too slow
The same regular expression used for larger texts show how slow Rhino’s RegExp support is.

Performing the replacement on the text from previous example repeated 100 times I get on my desktop:

Pure Rhino: 25 ms
String.replace using java.util.regex: 7 ms

and if I repeat it 1000 times this becomes even worse:

Pure Rhino: 440 ms
String.replace using java.util.regex: 15 ms

Quite impressive difference!

HtmlUnit’s first step to use java.util.regex based JS RegExp
Ideally the Rhino RegExp support should be rewritten to use java.util.regex. This will surely come in the future but it is not yet the case.
Luckily the String functions that need regular expression don’t use the RegExp functionalities directly but through a proxy that can be configured through ScriptRuntime.setRegExpProxy. This is what

script.aculo.us drag & drop now works for HtmlUnit

I wanted since a long time to be able to test drag & drop features with HtmlUnit like those of script.aculo.us demo shop.

This was a long work to implement all missing js functionalities. Particularly script.aculo.us’ drag & drop requires that information on elements’ position in the page are available but HtmlUnit doesn’t compute any rendering information (what makes it very fast). The solution was to compute faked positioning information: the position isn’t important by itself, it just needs to be coherent with the information of the mouse event.

The result is that it is now possible to test drag & drop on the demo shop:

public void testDragAndDrop() throws Exception
{
final String url = "http://demo.script.aculo.us/shop";
final WebClient webClient = new WebClient();
webClient.setAjaxController(new NicelyResynchronizingAjaxController());


final HtmlPage page = (HtmlPage) webClient.getPage(url);


final HtmlElement mug = page.getHtmlElementById("product_1");
final HtmlElement cart = page.getHtmlElementById("cart");
assertEquals("check that the basket is empty", 0,
cart.getByXPath(".//img").size());


mug.mouseDown();
cart.mouseMove();
cart.mouseUp();


assertEquals("check that the basket now contains 1 element", 1,
cart.getByXPath(".//img").size());
}

Quite simple, isn’t it?

Update 31.03.08:

I’ve changed the XPath expressions from //img to .//img for compatibility with upcoming HtmlUnit 2.0.