How to Create and Mark Tests Using Wufoo, Python and Django

Wufoo makes invigilating, administering and marking tests easy.

Not already signed up for Wufoo? Let's get started!

By: Robert Graham

This is a tutorial from guest blogger Robert Graham. He wrote a very cool bit of software on the Django framework for Python that is able to mark tests built from Wufoo forms. This tutorial is a bit more technical than what we usually serve up here, so if you're a casual user, be prepared for some hardcore code action.

Basic Features

This software (“wufoo_quizzes”) is able to extend the functionality of Wufoo by turning survey-like forms that you build with Wufoo into tests that are marked. The user completing the test receives an email giving his/her results or a certificate if he/she “passes”, and the admin can receive an email of the complete results of the test as a CSV file.


Step 1) Have a Wufoo Account and Create a Test

First, you'll need a Wufoo account and a survey to use. The example I have tested this module with is about WWII history. Each test that you use with this module will need a Name and Email field. Test questions are multiple choice fields, so they have one correct answer.

Building Test

Go ahead. Make your Wufoo test. I'll wait. If you just want to follow along with this tutorial exactly, we’ve put this exact test into the Wufoo Template Gallery.

Test in Gallery

Just click the Add to Wufoo button and it will be added to your Wufoo account.

Step 2) Environment Setup

Now you need to prepare a place to run the test marker from. Let's make a virtualenv for that. You may be asking why. David Fischer makes it clear:

If you develop a Python module and you don't test it with virtualenv, don't make your next release until you do. Virtualenv creates a Python environment that is segregated from your system wide Python installation. In this way, you can test your module without any external packages messing up the result, add different versions of dependency packages and generally verify the exact set of requirements for your package.

If you don't have virtualenv:

  pip install virtualenv

Environment setup:

virtualenv --no-site-packages grader
source ./grader/bin/activate
pip install python-dateutils
pip install django

This prepares a Python environment that does not connect to your local root site-packages for dependencies and installs two of the three dependencies for this project into it. Now, download the code for wufoo_quizzes if you have not already. Unzip that in your choice location. Finally, we download our last dependency, pyfoo, which allows us to talk to the Wufoo API from Python. Unzip the .zip file you download from GitHub, then place and the scripts folder into the same directory that contains from wufoo_quizzes.

Step 3) Quiz Answers and Settings

Edit the answers.txt file in the wufoo_quizzes folder to contain the name of your test followed by new lines in a question: answer format.


WWII History Test
Which country or countries benefitted from the Lend Lease Pact?: Both
Which is a German field commander who fought a brilliant campaign on the Eastern front?: Manstein
When did the Allies break out of Normandy?: August 1944

You can place more quizzes in this answers file like so:

WWII History Test
Which country or countries benefitted from the Lend Lease Pact?: Both
Which is a German field commander who fought a brilliant campaign on the Eastern front?: Manstein
When did the Allies break out of Normandy?: August 1944

Other Test Name
Question 1: True
Question 2: False
Question 3: Honey Badger
Question 4: Vegas, Baby!

Make sure the question and answer text exactly matches what is on your Wufoo form. I copied and pasted mine directly from Wufoo after finishing the form.

You will also need to configure settings by creating a file named ‘' in the same directory as from wufoo_quizzes. You can copy and paste what you'll need from or the example setup below:

email_password = 'pw'
api_key = 'APIKEY'
wufoo_account = 'account' # this is the 'youraccount' part of
smtp_host = ''
email_user = ''
templates = ('/your/path/to/this/project/', '/your/path/to/the/template/dir')
admin_email = ''
admin_email_subject = 'Quiz Results'
success_message_text_alt = "This is an text only alternative message for those users pass the quiz"
required_score = 80.0 # 80% to pass
send_user_emails = False
send_admin_email = True

Step 4) Time to Take Over the World

Run the marker, receive emails, change your life! (Make sure you activate the virtualenv as above first.)

python path/to/

You should see something similar to:

GreenEyedDevil:rgraham-wufoo-quizzes-tip rgraham$ python 
WWII History Quiz Scores: scored 0.00 percent on WWII History Quiz. scored 100.00 percent on WWII History Quiz.
Sending failure message to:
Sending certificate to:

Users who fail the test will receive a text email from the template failure.txt like this:

Quiz Failure

Users who pass the test will receive an HTML email from the template certificate.html like this:


The admin will receive a text email from the template weekly-email.txt like this:

Admin Quiz Results

The templates used to send emails are examples that you are welcome to use, but you may want to include your own information in them. These templates use the Django template system and can easily be modified to suit your purposes. Major changes such as which data is dynamically included in the templates will require you to modify the code, but any static changes can be made as easily as changing any text file.

Step 5) Extra Credit

Set up this script to run using cron. If you'd like to get results only from the last week, you can make some small changes to to make that happen. Uncomment the if statement where you see (2 locations):

# FIXME make the date specifiable
#if datetime.datetime.strptime(entry[date_created.ID], "%Y-%m-%d %H:%M:%S") > ( + relativedelta(weeks=-1)):

Changes weeks=-1 to whatever date range you have in mind. weeks=-2 for the last two weeks of results. days=-1 for the last 24 hours of results. You will probably connect this interval to your cron interval.


This is a fairly lightweight solution that is not suitable for extremely high traffic forms, but it might be just right for you or provide you with a starting point for building something more robust.


You can also email me with requests or issues. I'll do all I can to help. Thanks for following along and happy testing!

Robert Graham is a developer, software entrepreneur and consultant who maintains a blog about the experience. Robert has been working in software since 2005. He is a Ph.D. dropout who has spent some time working for Google. One day, he'd like to work for himself.