I've been working on an App Engine project for the past couple of months. This is my first (and probably last) time working with the GAE Python Standard Environment.
One of the things I found most frustrating about the environment is the lack of support for running functional tests against the GAE testbed. Because I'm used to Django's LiveServerTestCase, it seemed impossible to me that there is no solution for this.
Well, eventually I found it. The secret ingredient lies within the
http module in
the Webtest library.
We create two mixins to use with the test. The first sets up the testbed, and the second starts the app server in a different thread.
from google.appengine.ext import testbed from webtest import http from main import app # your WSGI app class TestBedMixin(object): def setUp(self): super(TestBedMixin, self).setUp() self.testbed = testbed.Testbed() self.testbed.activate() self.testbed.init_datastore_v3_stub() self.testbed.init_memcache_stub() self.testbed.init_user_stub() self.testbed.init_taskqueue_stub() # add other stubs you may need def tearDown(self): super(TestBedMixin, self).tearDown() self.testbed.deactivate() class LiveServerMixin(object): def setUp(self): super(LiveServerMixin, self).setUp() wsgi = WhiteNoise(app, root=static_path, prefix='static/') self.server = http.StopableWSGIServer.create(wsgi) self.url = self.server.application_url[:-1] # remove trailing slash def tearDown(self): super(LiveServerMixin, self).tearDown() self.server.shutdown()
Now we can write our test:
from selenium import webdriver from models import MyModel class TestSomething(TestBedMixin, LiveServerMixin, unittest.TestCase): def test_some_thing(self): driver = webdriver.Chrome() driver.get(self.url) # do stuff with selenium # ... # check that something was created in the datastore created = MyModel.query().count() > 0 self.assertTrue(created)
This has solved a lot of headache for me.
You'll have notice the wrapping of the app in a Whitenoise class – this is for serving static files.
Because you're not using the
dev_appserver.py with your
app.yaml, you need to serve static files somehow.
Check out Whitenoise for more details.