I’ve recently been working on a project trying to take an existing customized wordpress site and create automated integration tests around parts of it. I’m using phpUnderControl, phpUnit, Selenium RC, Firefox, Xvfb (virtaul frame buffer) and … well, I think that’s it.
So, phpUC is configured to do a checkout from svn on a commit, then run tests. I have a few base unit tests written, then a set of integration tests. The integration tests are written in phpUnit and use the Selenium integration to launch a Firefox browser in a virtual frame buffer and then interact with the browser programmatically. The basics work fine, and I’ve had some basic success after not *too* much setup time.
The first problem I ran in to was with wordpress. WordPress will only work on the configured ‘siteurl’ (which is configured in the database). I did a dump of a dev db from a different server, then brought that over to the qa server and set up a wp db, then pointed the svn ‘checked out’ code to that database. Every time I hit the qa server it was redirecting me to the original server. After some futzing around, I realized the problem – ‘siteurl’ and maybe another config are set in the database. The short solution was to search/replace through the MySQL dump the reimport that for the QA installation. Worked fine. I don’t think this is an ideal solution, but it got me through the initial hump.
Second problem is much more subtle (insidious, even). The original dev site was at dev.mainsite.com. I moved it over to qa.generalsite.com/project/. Even after switching the ‘siteurl’ in the WordPress MySQL dump, I ran in to problems. The templates all were written to be relative to a site running at the root (in this case, dev.mainsite.com). All css and js were looking for “/js/myjs.js” and “/css/mycss.css” and so on. There’s no easy fix for this without having to actually go in and forecefully make the templates use full paths. I *can* in this case add new domain names (I could make “qa_project.generalsite.com, for instance), but this is less than ideal.
Why is it less than ideal? Well, it’s not a process that everyone can engage in. To make something testable now requires that I have access to manage the DNS and add virtual hosts. This is just not something that everyone can do. The original option – modifying core code for a project – is doable, but likely not something many people will end up doing. They’d probably just skip automated testing rather than have to make the code testable in the first place.
Obviously *writing* a system that’s testable from day 1 would be better, but most systems aren’t built that way, and because many people don’t test much (or at all), the concept of a ‘testable’ system is just not high on their list of priorities. I took over a system a few years ago that announced all system messages on the site via an ‘alert’ in the body’s “onload” method. This was the *one* case that Selenium couldn’t deal with. That’s not to say that no automated browser managers could handle it – Silk Performer could, and some others, but they also cost money that not everyone can spend.
In my view, for code to be testable (both unit and integration testing) it needs to be portable. The code should be able to be checked out and set up in a new server environment with a minimum of steps and time. The entire process should be able to be scripted (in other words, a build process) and eventually automated, but it’s not something I shoot for right out of the gate with existing legacy code. The process of making the code portable (and therefore more easily testable) is not something that will often come quickly, and will likely be something you’ll need to work towards while doing the ‘real’ work.
As I aluded to earlier, the code needs to be portable both from a code standpoint but also from a ‘front end’ standpoint. If relative URLs are used in the HTML, use a “base href” tag at the top which is filled in with a dynamic parameter set in a config file. In PHP, set a constant indicating a base path, and make include() statements reference the constant. *Don’t* hardcode include_path in an .htaccess file. Why not? .htaccess files are only ‘valid’ in the context of a web server running. If you want to run unit tests from a command line, your code will simply not work.
What steps have you taken to make sure your code (both backend and frontend) is testable?
I'm currently working on a book for web freelancers, covering everything you need to know to get started or just get better. Want to stay updated? Sign up for my mailing list to get updates when the book is ready to be released!