Testing
####Different kinds of testing If you check the article on software testing on Wikipedia, you will see there are many kinds of testing.
But in this post we are going to look specifically at testing webapp2 handlers on App Engine.
Setting up a test environment for App Engine applications is a little bit fiddly, but is not hard to do. We are going to use the NoseGAE plugin for nose, a widely-used extension to the unittest unit testing framework.
Testing is a big topic and we are just touching the surface here, but following the instructions below will get you to the point where you can build some simple functional tests for your application and begin to explore further.
####Getting set up
First, install the the WebTest framework for testing WSGI applications:
pip install --user webtest
(you can also use sudo pip install webtest
)
Then, install the nose testing framework:
pip install --user nose
And, finally, install NoseGAE:
pip install --user nosegae
####Create a very simple App Engine application
Use the Hello World example on GitHub:
git clone https://github.com/GoogleCloudPlatform/appengine-helloworld-python.git
Amend the main.py file like this:
import webapp2
class MainHandler(webapp2.RequestHandler):
def get(self):
self.response.write('Hello world!')
#app = webapp2.WSGIApplication([
# ('/', MainHandler)
#], debug=True)
def application():
return webapp2.WSGIApplication([
('/', MainHandler)
], debug=True)
if __name__ == '__main__':
wsgiref.handlers.CGIHandler().run(application())
else:
app = application()
We can now create a WSGIApplication object in two different ways; either the usual way via the app.yaml file or via wsgiref
as a script, for testing purposes.
Create a test file (you can call it test.py):
from webtest import TestApp
from main import application
app = TestApp(application())
def test_index():
response = app.get('/')
assert 'Hello world!' in str(response)
Now run:
nosetests -v --with-gae
If you get the error:
ImportError: No module named dev_appserver
Then, check where dev_appserver is being served from:
which dev_appserver.py
>>>/home/action/.google_appengine/dev_appserver.py
And run:
nosetests -v --with-gae --gae-lib-root="/home/action/.google_appengine/"
(or whichever path dev_appserver.py
is on)
You should get something like:
test.test_index ... ok
------------------------------------------------
Ran 1 test in 0.123s
OK
You now have a single passing test. Congratulations!
####Apply testing to your blog application
Make the same changes as above to your main blog application file, using the application() function. And add a test file to your application.
Now add some new tests. They might look something like this:
def test_index():
response = app.get('/')
assert 'Hello, Udacity!' in str(response)
def test_index():
response = app.get('/blog')
assert 'CS 253 Blog' in str(response)
These kinds of tests, where the output of the handler functions is tested against expectations, are known, appropriately enough, as functional tests.
Functional tests are based around the functions that a piece of software are expected to perform. In the case of the webapp2 framework, this means faking HTTP requests and checking that the handler functions return the expected responses.
####Unit tests
Unit testing is beyond the scope of this post, but is generally applied to a single class or module within an application.
Within the context of a web app, you would expect unit tests to be applied to models.
Nosegae has a nice approach to unit testing, which involves using doctest
.
We haven’t covered doctest yet, but Wikipedia has a good introduction.