Search code examples
google-app-enginewebapp2python-unittestwebtest

Local unit testing for Google App Engine + Python WebApp2


I have a really simple web app. All the important stuff happens in index.py:

from google.appengine.api import users
import webapp2
import os
import jinja2

JINJA_ENVIRONMENT = jinja2.Environment(
    loader=jinja2.FileSystemLoader(os.path.dirname(__file__)),
    extensions=['jinja2.ext.autoescape'],
    autoescape=True)

def get_user():
  user = {}
  user['email'] = str(users.get_current_user())
  user['name'], user['domain'] = user['email'].split('@')
  user['logout_link'] = users.create_logout_url('/')
  return user

class BaseHandler(webapp2.RequestHandler):

  def dispatch(self):
    user = get_user()
    template_values = {'user': user}
    if user['domain'] != 'foo.com':
      template_values['page_title'] = 'Access Denied'
      template = '403'
    else:
      template_values['page_title'] = 'Home'
      template = 'index'
    template_engine = JINJA_ENVIRONMENT.get_template('%s.html' % template)
    self.response.write(template_engine.render(template_values))

app = webapp2.WSGIApplication([
    ('/', BaseHandler),
], debug=True)

I'm trying to be a good person and write some local unit tests but - after looking at the documentation - I am totally out of my depth. All I want is a basic framework where I can do something like:

python test_security.py 

and simulate two users hitting the domain - one @foo.com who should get the index template, and one @bar.com who should get the 403 template.

Here's where I've got so far:

import sys

# I don't want to talk about it, let's just ignore this block
sys.path.append('C:\Program Files (x86)\Google\google_appengine\lib\webapp2-2.5.2')
sys.path.append('C:\Program Files (x86)\Google\google_appengine\lib\webob-1.2.3')
sys.path.append('C:\Program Files (x86)\Google\google_appengine\lib\jinja2-2.6')
sys.path.append('C:\Program Files (x86)\Google\google_appengine\lib\yaml-3.10')
sys.path.append('C:\Program Files (x86)\Google\google_appengine\lib\jinja2-2.6')
sys.path.append('C:\Program Files (x86)\Google\google_appengine')
sys.path.append('C:\pytest')


# A few proper imports
import unittest
import webapp2
from google.appengine.ext import testbed

# Import the module I'd like to test
import index

class TestHandlers(unittest.TestCase):
   def test_hello(self):

       self.testbed = testbed.Testbed()
       self.testbed.init_user_stub()
       self.testbed.setup_env(USER_EMAIL='test@foo.com',USER_ID='1', USER_IS_ADMIN='0')

       request = webapp2.Request.blank('/')
       response = request.get_response(main.app)

       print "running test"

       self.assertEqual(response.status_int, 200)
       self.assertEqual(response.body, 'Hello, world!')

Predictably, this doesn't work at all. What am I missing? Am I just wildly overestimating how simple this should be?


Solution

  • If you're planning on invoking this with "python test_security.py", the magic words you are looking for are:

    if __name__ == '__main__':
        unittest.main()
    

    This will make your unit test run - at the moment all you're doing is defining it.

    Note also that you'll need to change your request.get_response from "main.app" to "index.app".