Browser-Side Test
From Ajax Patterns
There's an archived version of this pattern available, taken from the Ajax Pattern book draft, showing roughly how it appeared before the page became publicly editable.
Evidence: 1/3
Tags: Automated IntegrationTest Javascript Regression UnitTest TDD Test
Contents |
|
Goal Story
Devi is about to embark on upgrade a blog reader and realises she will be working on the Javascript RSS parser. It will need some refactoring, but fortunately there's already a Javascript unit test for it. She proceeds to refactor the parser, ensuring the test still passes, and continues to enhance the test as she builds in further functionality.
Problem
How can you test Javascript components?
Solution
Create automated tests of browser-side Javascript components. This pattern is a mapping from automated testing in other languages, where frameworks like the [xUnit series] (e.g. JUnit) are now popular. Several frameworks do the same for Javascript. As with other languages, you can unit-test an individual Javascript component (e.g. a function) you've created, and also perform integration tests and system tests that work across several objects. And also like other languages, you can accumulate tests into a test suite object, so it's possible to run a full regression test.
The test is usually some Javascript, executed from the browser by clicking a Start button. It will then perform some DOM manipulation to show the result. So the test is automated insofar as the programmer's not manually interacting with the application and verifying results. That's good enough while developing, the demands of continuous integration suggest we need to go beyond that. How do you allow a tool like Make or Ant or Rake start and stop a Javascript test?
One way to co-ordinate a Browser-Side Test is to simulate browser behaviour. Using a Javascript engine, you can programmatically execute some Javascript code. For example, Java programmers have the Rhino library (a standard component of Java 6). If there's some DOM manipulation involved as well, an approach like Browser Simulation, discussed in System Test can be used. A second approach is to fire up a real browser using a shell command, specifying the test page as an argument. The test framework will then run in the browser, and the page must be configured to upload results to a service somewhere, which will expose them to the test process. The test process, upon detecting new results, then kills the browser process.
Tool Support
WebAii (artoftest)
WebAii is a .NET automation library provided for free to the quality assurance and developer community. It is built for Ajax and rich web application automation. Currently supports (IE,FireFox) (more browsers are planned). Plugs-in Visual Studio environment. Also supports a new approach to abstracting markup applications using TestRegions. Use with NUnit or Visual Studio Team Test.
- Commercial from ArtOfTest, Inc. Provided Free of charge.
SWEA (webius)
SWEA automates regression and functional testing for Web applications. The program creates an automation API for any Web application developed with HTML, DHTML or AJAX. The Web application becomes programmatically accessible from any .NET language. SW Explorer Automation Visual Designer records, replays test scripts and generates C# or VB.NET script code which can be used in NUnit or Visual Studio unit tests.
- Commercial from Webius. Provided Free of charge.
Scriptaculous
The Scriptaculous framework includes a unit-testing framework. It works similarly to the earlier JsUnit frameworks (below) and the nUnit frameworks they are modelled on. A test case is an object containing a sequence of methods beginning with "test", e.g. testStringMatches(), and optional setup() and teardown(). The test is passed to a testrunner object. For each test method, the runner executes setup(), then the test method, then teardown(). The runner updates the UI and reports on the results.
As with many Scriptaculous classes, the Runner object accepts an options argument. A particularly interesting option is resultsURL, which the runner will post results to, a facility that makes automated testing possible as discussed in the Solution.
Scriptaculous also contains some functions that let you simulate mouse and keyboard; see System Test.
Selenium
Selenium is a browser-side functional test tool for web applications. It includes Selenium IDE, a test record/playback tool, Selenium RC, a tool that lets you write your tests in any programming language (including Java, .NET, Perl, Python and Ruby) and Selenium Core, a "browserbot" automation library.
JsUnit (Hieatt)
Edward Hieatt's JsUnit is a testing framework that supports standard xUnit-like functionality. Each test is actually an HTML page containing the test in a script, and the HTML page is passed as an argument to a test runner page. There's a demo page available.
JsUnit (Schaible)
Jorg Schaible's JsUnit works similarly to the above frameworks.
Squish/Web (froglogic)
Squish is an automated, functional testing tool. It allows to record, edit and run web tests in different browsers (IE, Firefox, Safari, Konqueror, etc.) on different platforms without having to modify the test scripts. Supports different scripting languages for tests.
- Commercial from froglogic
Refactoring Illustration
The Basic Ajax Pattern Reader uses a queue abstraction to represent the playlist. The queue itself was developed with a Scriptaculous test case. The setup method establishes a new queue:
setup: function() { with(this) {
q = new Queue();
}},
setup: function() { with(this) {
An initial test method verifies the queue's initial state:
testEmptyQueue: function() { with(this) {
assertEqual(0, q.size);
var items = q.items();
assertEqual(0, items.length);
}},
Subsequent methods examine the queue as it's built up:
testSequence: function() { with(this) {
q.admit("first");
q.admit("second");
assertEqual(2, q.size);
assert(util.membersEqual(["second","first"], q.items()));
...
}},
All of this is embedded an HTML file, which if you visit it, will run the test and report the results. The structure of the HTML file is shown below.
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Queue Test</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<script src="/run/Lib/js/util.js" type="text/javascript"></script>
<script src="prototype.js" type="text/javascript"></script>
<script src="unittest.js" type="text/javascript"></script>
<script src="queue.js" type="text/javascript"></script>
<link rel="stylesheet" href="test.css" type="text/css" />
</head>
<body>
...
<!-- Log output -->
<div id="testlog"> </div>
<!-- Tests follow -->
<script type="text/javascript" language="javascript" charset="utf-8">
new Test.Unit.Runner({
q: null,
setup: function() { with(this) {
q = new Queue();
}},
testEmptyQueue: function() { with(this) {
assertEqual(0, q.size);
var items = q.items();
assertEqual(0, items.length);
}},
...
});
</script>
</body>
</html>
Related Patterns
Service Test
A Service Test is a good way to complement a Browser-Side Test, since it focuses on the server-side interface rather than the browser application. Testing both is necessary to be confident that all aspects of the system are working.
Logging
Logging inside a test can help diagnose problems.
Time your website with
WebWait - from the creator of AjaxPatterns.org
