If you type Drupal and JMeter in to Google, you'll probably turn up this useful blog post fairly quickly:
This is a great "quick start" guide to basic testing of a Drupal application with JMeter, but it only scratches the surface, by the author's own admission.
In this post I'd like to duck our heads just beneath the surface and touch on another fantastic use for JMeter: as a deployment tool. While this post is specifically about Drupal, the techniques discussed can equally be applied to any web-based application where you want to automate a bunch of tedious installation steps that occur via form submissions in a web-based UI.
First, the justification:
If you've ever worked for a large IT company with a department of system administrators, you will already know how much they hate user interfaces and wordy, descriptive release notes. Scripting is king and less is more!
I used to think this was a pain, as a development manager, because it meant finding the charred remains of my lovingly crafted release notes, all 27 pages of step-by-steppy goodness, smoking in a rubbish bin in the car park. And a viciously sarcastic email in my inbox along the lines of having other applications to deploy this year too.
My team thought it was even more of a pain, because they had to spend an extra day or so at each release writing deployment scripts, which made them very grumpy indeed.
But not half as grumpy as when the San Francisco based deployment team called them on their mobile telephones at 0300 GMT to ask them to clarify exactly which files from the package needed to be copied to the 'foo' directory. Just the DLLs? No? Oh frack. Roll back!
Documentation, even with screen-shots and minute detail, is always ambiguous. Written language is ambiguous.
Then there's human error. Sure, there's human error potentially present in deployment scripts too, but stage environments are there to iron those bits out. And if there's an error in a deployment script, chances are the developer can fix it in minutes.
Conversely, if there's an error because Joe Sysadmin missed a step, he thinks, or maybe not, perhaps it's a bug? Hours of head scratching and phantom bug hunting ending in a frustrated sysadmin and a failed release which, for all you know, might actually be fine. But you still have to go through it with a fine-toothed comb, because it might also not be fine at all, and you have no way of knowing. Nightmares!
After a while you start to realise scripts are great: they either work or they don't. No middle-of-the-night phone calls, no frustrating misdirected bug reports, no queries, one of two things happens:
- the script didn't work so the sysadmin restores the backup and fails it, noting the script that failed and any error messages
- the script did work and everybody's happy
The key point is you should be aiming towards a deployment strategy that means someone with absolutely *no* experience of your application whatsoever, but a decent grasp of Linux, can successfully handle an upgrade without any assistance. Heck, if you've done it really well they don't even need a decent grasp of Linux! And one major hurdle to overcome is the need to do many fiddly admin settings in the back-end of Drupal to complete an upgrade.
Now the actual technique:
Enter JMeter. While you may be familiar with JMeter as a testing tool, you can use it to record and replay admin steps in the UI automatically. And JMeter scripts can be executed from the command line, so all you need to give your system administrators is a command to copy and paste. They will love you so much, they will never tear up your release note and stuff the shreds in to your nostrils again. They *may* even make you a coffee.
So how do you go about this? Well you can do most of the basic setup using the post I linked to at the start, in conjunction with the second part. But what those posts do not cover is how to submit forms which is, of course, precisely what you need to be able to do. At the end of the second page, the author of the above notes the issue around form tokens, and this is what we solve here:
Assuming you've read the above and you're all set up using JMeter as a proxy, the first thing you will need to do is an admin login. I tend to start by recording a login, followed by a logout. I then copy the logout sampler and paste it in place just prior to the login attempt, just to make sure I'm starting with a nice, clean session. I often save this "stub" test plan as a starting point for future ones.
Next I start recording my form actions. So, for this example, let's imagine we are changing some user permissions. Browse to the user permissions page and you'll see the samplers building up in your Recording Controller. When you hit the permissions form, pause for a moment and delete the rubbish (that is all samplers, except for the one just created - and the login/logout ones, obviously).
Now set permissions how you want them and save your form. Another sampler will appear. Select this sampler and right-click it the test plan pane, on the left of JMeter. Select the following:
Add -> PreProcessors -> HTTP Link Parser
It has no settings, so there's nothing more to do there. This PreProcessor looks at the most recent previous execution of the same URL by JMeter, in the current thread group, and compares any HTML element IDs present to see if they still exist in the current execution. If they do, it stores the original value, which can be used in the present step. How?
Select your second sampler again and it should have a load of request parameters set in the middle of the right-hand pane (the form values to be sent). Find the one called 'form_token' and replace the value with this:
Nothing else, just that. JMeter recognises this as a regular expression meaning "everything!" and the Link Parser will substitute the current value for form_token with the value from the previous page load, making them match so our form submission will validate and not be considered spam.
And that's it. One deployment that automatically updates user permissions for you. Just run your test and you will see it automatically change your settings. Want to apply the same settings to an entirely different server? Simply change the HTTP Request Defaults to point to the server where the settings need to be applied and run the test.
You might also want to add some Response Assertions, to verify your form was correctly submitted (perhaps looking for an expected confirmation message) but I'm sure I can leave you to figure that out.
As you can imagine, now you can login as an administrator and execute automated form submissions against Drupal's admin pages, you can knock yourself out. You can script all the steps you would otherwise have to list in a document and all your sysadmin needs to do is execute the test plan. Just keep stringing out your form submissions to your heart's content!
There is one caveat:
In some cases the data is posted, via a redirect, to a page with a different URL to the initial form (an example is the system module page) and in this case the HTML Link Parser approach will not work, because it doesn't make the connection between the differing URLs. You need a Regular Expression Extractor (see Post Processors) on the initial sampler - the one with no parameters - to extract the form_token value and save it in a variable. The Extractor settings need to look like this (for Drupal 6.x):
Response Field to Check: Body
Reference Name: form_token
Default Value: NOT FOUND
In the second sampler, where the data is actually submitted, the form_token parameter needs this value, instead of the
.* it was before:
Note, this approach, while more complex, will always work whereas the HTTP Link Parser approach may not.
I'm going to follow this up at a later date with a post about my personal ideal Drupal release, script samples, etc. But that's for another day.