Unit testing for Google App Engine with Python

14 Jun 2011

Tags: python, testing

I recently inherited a python project that used Google App Engine, and didn’t have any unit tests setup, which is something I wanted to fix. My main aim was to get to the point where I could test it like I did any Django app I’ve built (this GAE project does not use Django) - basically I wanted to be able to do tests where I can:

  • Query the database to check what I expect to be in it is
  • Call URLs on the app to check that the external interface works as expected

There’s a little documentation on getting started with local unit testing for Python, but it’s not clear from that how to run the tests, and there’s no help on how to call URLs on your app that I could see. Thus, I thought I’d document how I got setup:

Infrastructure

First get setup to run the tests. I’m assuming you already have the GAE SDK for Python installed. Next I installed the following:

  • Python nose - testing framework for python, can be installed with “easy_install nose”.
  • Nose plugin for GAE - a plugin that adds support for GAE. I downloaded and installed from tarball.
  • webtest - a framework that makes it easy to test WSGI apps. Can be installed using “easy_install webtest”.

That’s all the pieces. Once installed we’re ready to start writing our unittests.

Writing tests

Nose, if you’ve not used it before, will look through your project for unittests and run them. That said, I still like to have them in an easy to find place, so I create a “tests” module in the root of my GAE project director.

% cd [path-to-my-project]
% mkdir tests
% touch tests/__init__.py

In the tests directory I create a python file for each test class, and in __init__.py you should import that that class. So, if you had a myfirsttest.py that had a test class in it called MyFirstTest then your __init__.py would look like:

from myfirsttest import MyFirstTest

Now, what does that class look like? Well, lets write a test that will test loading the root path on our GAE server. The code for that would look a little like this:

import unittest
from webtest import TestApp

from google.appengine.ext import db
from google.appengine.ext import testbed

from my_gae_app import application

class MyFirstTest(unittest.TestCase):

   def setUp(self):
      self.testbed = testbed.Testbed()

      # Then activate the testbed, which prepares the service stubs for use.
      self.testbed.setup_env(app_id='my_gae_app_id')
      self.testbed.activate()

      # Next, declare which service stubs you want to use.
      self.testbed.init_datastore_v3_stub()

      # create a test server for us to prod
      self.testapp = TestApp(application)

   def tearDown(self):
      self.testbed.deactivate()

   def testFetchRootURL(self):
      result = self.testapp.get("/")
      self.assertEqual(result.status, "200 OK")

That gives you some idea of how to structure the test. The import of application is the application you create as part of your GAE project. You should have some code somewher that looks like:

application = webapp.WSGIApplication([ bunch of url handlers specified here])

def main():
   util.run_wsgi_app(application)

if __name__ == "__main__":
   main()

That’s the application you give to webtest to wrap.

Also note that you import your data models and start using them or db.GqlQuery etc. in your tests.

Having written all that, you then go to the root director of your project and run it like so:

% cd [path-to-my-project]
% nosetests --with-gae
.
----------------------------------------------------------------------
Ran 1 tests in 0.396s\r\n\r\n    OK

Hopefully this’ll help you get started at least - it took me a lot of head scratching to get that far, so I hope it can be of use to others and save them that head scratching time :)

Digital Flapjack Ltd, UK Company 06788544