Test driven development has advantages all around– one of them being that it saves you time. And what’s a good use of this time? Why, coming up with novel ways of testing, of course. I had one of those experiences the other day thinking of ways to go about profiling memory usage of a web application (by which I mean, the server-side component of a GWT-based application currently in development).
At it’s heart, the problem was simple enough: execute a few thousand service method calls with semi-random data, and see what happens to memory over time. I considered writing a standalone Java application, or culling through existing testcases for some kind of integration test which provided enough coverage to be "interesting", and decided that what I really wanted to do was exercise the system through its front door. I pulled out JMeter but soon had a realization: "we’re writing a GWT app.. why not just write another GWT app to exercise the same services methods as we otherwise do, but in a manner I need?" So that’s what I did.
This turned out to be a very expedient and promising solution.
Fifteen minutes later I had a new, deployable GWT module which
inherited my existing application’s module but defined a new entry
point. I created a simple UI (by which I mean, a Button) and wired it
up to trigger a few thousand invocations of the particular service call
I had in mind.
For purposes of this specific application, I needed a measure of
randomness when passing an argument to my method within the loop. I
was able to use com.google.gwt.user.client.Random to do my quick &
dirty work for me:
// construct random string of 8 characters
String name = ""
for (int i = 0; i < 8; i++) {
name = name + (char) ('a' + Random.nextInt(26));
}
This proved more than adequate for my needs As for executing the
GWT-RPC call, it's important to remember that GWT-RPC calls execute
asynchronously, so control will always be returned to the main thread
right away. I created a new Timer instance and used Timer's
"scheduleRepeating()" method in order to space out my calls over time
(just be sure to call 'cancel' after you have finished your test run).
Since my goal here was not strictly to stress test, I was not
interested in controlling the exact number or rate of simultaneous
calls. Once I kicked off the test in the browser, I switched to my
back-end profiler, and did most of my work monitoring how the heap
space behaved over time.
A few minutes later, I thought of another test, so I added another
"label + button" combination to this GWT application, and wired it up
to a different service method. This particular method required its
arguments to represent existing data from the database. In two
minutes, I wrote a SQL query to grab two columns of sample data, copied
the results into TextMate, applied a regex transformation to turn them
into executable code (i.e. storing them in a HashMap) and pasted the
results into my test class. Iterating over these values, this test
used each pair of values as input into my service calls (about 400
separate calls, spaced 100ms apart). Back to the profiler I went.
In this case, I was able to go from idea to execution in minutes.
Being left with a UI at the end has additional benefits-- I could add a
text box to allow myself to parameterize these 'tests' within the
browser, display a running status of the test (a simple counter of how
many service calls have been made is trivial), etc. The best part?
This type of app can easily be shared throughout the development team,
or deployed to an internal environment for profiling on other systems
(remotely). Building this kind of "development-only" console along
with the real application can be helpful to the development effort. It
may also invite other developers to do things like profile more often,
instead of pushing it off to some non-existent future.
