Tonight, I've been working on the unit testing framework for
severedelays.org. I started out with a basic web search that lead me to
this article, which suggested mocking out all of the framework calls. This sounded great, but was really too much work for me to reliably do on a regular basis.
What I really wanted was something I could run from my machine to make sure that my code was ok without having to manually run through all of the possible pages in my app.
Next I came to
these suggestions by the App Engine team, however, this approach doesn't actually work very well on the mac because this platform uses the GoogleAppEngineLauncher, so none of the app engine code is installed in the python path. Again, I could get around this, but it's a bunch of work and my collaborators would have to do different work arounds for their platforms.
Finally I came to
GAEUnit, which was almost what I wanted. From a testing perspective, this solution is great, but if you look at the setup instructions, the authors suggest that you drop their gaeunit.py in your appengine directory, and create a /test* url in your configuration.
I don't like this for a couple of reasons. First I want to keep my test code seperate from my deployed application code. There is no reason to have to deploy my test code in my production application. The extra code can lead to confusion, and possibly to bugs. Also, I was nervous about adding another URL target that I would have to support, even if I can ensure that the tests self-destruct when they are run in production.
I came up with a workaround, that I'm pretty happy with. I created a second appengine configuration in our repository to house the tests, so now my code tree looks like this:
severedelays/appengine/... (This is where my production code lives).
severedelays/appengine-test/...(This is where my test code lives).
So, this allows me to keep my test code out of my production code. All I need to do to import my production code is to create a couple of relative soft links between the two directories for my
lib and
third_party directories.
Now, when I'm working on the code I can startup a dev sever for both appengine configurations. In the first I can test what the app looks like, and in the second I can run the tests.
This also has the advantage of seperating the datastore for the test instance from my development instance. Overall, I'm pretty happy with this setup.