A Framework For Automated Testing of Javascript Web Applications
A Framework For Automated Testing of Javascript Web Applications
Aarhus University
[email protected]
Anders Mller
*
Aarhus University
[email protected]
Frank Tip
IBM Research
[email protected]
ABSTRACT
Current practice in testing JavaScript web applications requires man-
ual construction of test cases, which is difcult and tedious. We
present a framework for feedback-directed automated test genera-
tion for JavaScript in which execution is monitored to collect in-
formation that directs the test generator towards inputs that yield
increased coverage. We implemented several instantiations of the
framework, corresponding to variations on feedback-directed ran-
dom testing, in a tool called Artemis. Experiments on a suite of
JavaScript applications demonstrate that a simple instantiation of
the framework that uses event handler registrations as feedback in-
formation produces surprisingly good coverage if enough tests are
generated. By also using coverage information and read-write sets
as feedback information, a slightly better level of coverage can be
achieved, and sometimes with many fewer tests. The generated
tests can be used for detecting HTML validity problems and other
programming errors.
Categories and Subject Descriptors
D.2.5 [Software Engineering]: Testing and Debugging
1. INTRODUCTION
JavaScript [6, 13] plays a central role in modern web applica-
tions. Although originally designed for simple scripting, modern
JavaScript programs are complex pieces of software that involve
intricate communication with users and servers. Compared to lan-
guages such as Java and C#, relatively little tool support is available
to assist JavaScript programmers with testing their applications. In
current practice, JavaScript programmers construct test cases either
manually or using unit testing tools with capture-replay facilities
such as Selenium, Watir, and Sahi. These tools provide functional-
ity for recording the GUI actions performed by a user in test scripts,
for running a suite of tests, and for visualizing test results. How-
ever, even with such tool support, testing remains a challenging
and time-consuming activity because each test case must be con-
in Worklist do
19. Worklist.reprioritize(c
))
20. end for
21. // make test inputs by modifying the last event in s
22. for each s
n
in (.generateV ariants(s
n
) do
23. add(u
i
, S, s
1
s
n1
s
n
)
24. end for
25. let S = c.getState()
26. if S / VisitedStates then
27. VisitedStates.add(S)
28. if c.hasFatalErrors() c.hasURLChanged() then
29. // make test inputs by extending s with a new event
30. for each p
in c.getEventRegistrations() do
31. add(u
i
, S, s
1
s
n
(.generateNew(p
))
32. end for
33. end if
34. // make test inputs starting from other URLs
35. for each u
i
in c.getURLs() do
36. add(u
i
, S, ([type = "main"], [], b
init
))
37. end for
38. end if
39. end while
40. return Results
41.
42. procedure add(TestInput c
):
43. Worklist.add(c
))
c.initialize(S) Sets the state of the browser and the web server
according to S.
c.load(u) Loads the web page with the URL u into the browser.
This causes the HTML contents to be parsed into a DOM
tree and JavaScript code fragments to be identied. No
JavaScript code is executed yet, and additional dynamically
generated JavaScript code may be identied later.
c.setFormFields(f) Fills out form elds (text elds, check-
boxes, etc.) in the HTML DOM tree according to the form
state map f. Form elds not covered by the map are unmod-
ied.
c.setBrowserParameters(b) Sets the browser parameters as
specied by the environment b.
c.triggerEvent(p) Creates an event from parameters p and in-
vokes the appropriate event handlers. During execution, it
records information about runtime errors and other anoma-
lies, code coverage, and registration and removal of event
handlers.
c.getState() Returns the current state of the browser and server.
c.hasFatalErrors() Returns a boolean indicating whether the
most recent invocation of c.triggerEvent lead to an un-
caught JavaScript runtime exception.
c.hasURLChanged() Returns a boolean indicating whether the
page URL was changed by the most recent invocation of
c.triggerEvent.
c.getMessages() Returns the set of errors/warnings encountered
in the most recent event sequence execution.
c.getEventRegistrations() Returns a set of partially initialized
event parameter maps corresponding to the event handlers
that have been collected by c.triggerEvent since the last
call to c.initialize.
(.generateNew(r
.
(.generateVariants(s
n
) Generates a set of variants of the event
s
n
by modifying the event parameter map, the form state
map, or the environment.
T.priority(c
. This de-
termines the order of exploration of the test inputs in the
worklist. When computing the priority, T may consult all
data gathered by c.
c.getURLs() Returns the set of URLs pointing to other pages of
the application (excluding frames), as collected by c. This
includes the URLs appearing in links in the DOM and direct
modications of window.location.
Figure 2: Pseudo-code for the main algorithm, along with a description of auxiliary operations that it uses.
event in the current test input (producing an event sequence of the
same length, but with different parameters), as shown on line 22,
(ii) by extending the current test input with a new event (producing
a longer event sequence), as shown on line 31, and (iii) by starting
from a different page URL, as shown on line 36.
On line 31, (.generateNew(p