I love Python's doctests. Basically, you test out your functions in the interactive shell and copy the results into the comments for a function. That's it! So simple.
Example:
def http_request(self, url, data, method=urlfetch.POST): """ Makes an API call to Triggermail and returns the response. >>> client = TriggerMail() >>> client.http_request('email', {'email':'EMAIL_REMOVED'}, urlfetch.GET) {u'blacklist': u'0', u'templates': {u'test2': 0}, u'verified': u'0', u'vars': {u'first_name': u'Aral', u'last_name': u'Balkan'}, u'optout': u'0'} """
To run the doctests, you just need a main method in your module that looks like this:
if __name__ == "__main__": import doctest doctest.testmod()
And, if you're working with TextMate, you can run the current script and its doctests by pressing ⌘ R.
Sweet!
However, when working with Google App Engine, this doesn't work out of the box.
If you try it, you'll get an error similar to the following:
ImportError: No module named google.appengine.api
This is because the local GAE environment isn't set up properly. The same goes when trying to test your apps from the Python interactive shell.
(If you're using Django for your app, you're in luck, all you have to do is ./manage.py shell and you're up and running with an interactive shell that's configured for your GAE project.)
Thankfully, Duncan over at the GAE forums went to the trouble of finding out exactly which imports are necessary to get you up and running.
His code listing actually goes beyond setting up the environment to finding your modules and running the tests. For my purposes, I just want to be able to hit ⌘ R in TextMate and run the tests for my current module while developing it, so I took the top bit of his code and put it into a module called gae_doctests.py.
It looks like this:
# To enable doctests to run from TextMate, import this module # (Use only when testing, then comment out.) # From: http://groups.google.com/group/google-appengine/browse_thread/thread/fa81f6abd95aa8b9/efed988b302aafb4?lnk=gst&q=duncan+doctests#efed988b302aafb4 import sys import os sys.path = sys.path + ['/usr/local/google_appengine', '/usr/local/google_appengine/lib/django', '/usr/local/google_appengine/lib/webob', '/usr/local/google_appengine/lib/yaml/lib', '/usr/local/google_appengine/google/appengine','/Users/aral/singularity/'] from google.appengine.api import apiproxy_stub_map from google.appengine.api import datastore_file_stub from google.appengine.api import mail_stub from google.appengine.api import urlfetch_stub from google.appengine.api import user_service_stub APP_ID = u'test_app' AUTH_DOMAIN = 'gmail.com' LOGGED_IN_USER = 't...@example.com' # set to '' for no logged in user # Start with a fresh api proxy. apiproxy_stub_map.apiproxy = apiproxy_stub_map.APIProxyStubMap() # Use a fresh stub datastore. stub = datastore_file_stub.DatastoreFileStub(APP_ID, '/dev/null', '/dev/null') apiproxy_stub_map.apiproxy.RegisterStub('datastore_v3', stub) # Use a fresh stub UserService. apiproxy_stub_map.apiproxy.RegisterStub('user', user_service_stub.UserServiceStub()) os.environ['AUTH_DOMAIN'] = AUTH_DOMAIN os.environ['USER_EMAIL'] = LOGGED_IN_USER # Use a fresh urlfetch stub. apiproxy_stub_map.apiproxy.RegisterStub( 'urlfetch', urlfetch_stub.URLFetchServiceStub()) # Use a fresh mail stub. apiproxy_stub_map.apiproxy.RegisterStub( 'mail', mail_stub.MailServiceStub())
(Either replace the /usr/local/ bit with the actual path to your GAE install or use Duncans code which is neater -- I was lazy and copied the contents of the sys.path list from the Django interactive shell.)
To use it, simply:
import gae_doctests
And hit ⌘ R in TextMate. Sweet!
Once I'm done hacking away on a module, I simply comment out the import.
The Running doctests from TextMate for Google App Engine modules article by Aral Balkan, unless otherwise expressly stated, is licensed under a Creative Commons Attribution-Noncommercial 2.0 UK: England License.
I tried it with textmate and it kind of works, but i still get a 404 error.
i think it has something to do with the google webapp framework for some reason probably “/” is not fetched? any hints on howto solve this while debugging or even setting which handler to call?
A brilliant aid to those of any IDE, thank you.
You may want to add:
>>> from google.appengine.api.memcache import memcache_stub
to your import section, along with:
>>> # Use a fresh memcache stub.
>>> apiproxy_stub_map.apiproxy.RegisterStub(
>>> ‘memcache’, memcache_stub.MemcacheServiceStub())
at the end of the file, negating memcache errors.
This seems like a daft question, but where did you put the gae_doctest module?