First of all, lets create a unit testing file that will run all our tests:
#!/usr/bin/python
"""
Runs all tests that exist in the tests directories.
The class should have a name based on the file's path, like this:
FilenameDirectory -> DefaultTasksModel
for example:
applications/app/tests/controllers/default.py
is
class DefaultController(unittest.TestCase)
BEWARE that the name is NOT in plural (controllers->Controller)
Execute with:
> python web2py.py -S appname -M -R testRunner.py
02/03/2009
Jon Vlachoyiannis
jon@emotionull.com
"""
import unittest
import glob
import sys
suite = unittest.TestSuite()
# get all files with tests
test_files = glob.glob('applications/'+sys.argv[2]+'/tests/*/*.py')
if not len(test_files):
raise Exception("No files found for app: " + sys.argv[2])
# Bring all unit tests in and their controllers/models/whatever
for test_file in test_files:
execfile(test_file, globals())
# Create the appropriate class name based on filename and path
# TODO: use regex
filename = str.capitalize(test_file.split("/")[-1][:-3])
directory = str.capitalize(test_file.split("/")[-2][:-1])
suite.addTest(unittest.makeSuite(globals()[filename+directory]))
# Load the to-be-tested file
execfile("applications/"+sys.argv[2]+"/"+directory.lower()+"s/"+filename.lower()+".py", globals())
db = test_db # Use the test database for all tests
unittest.TextTestRunner(verbosity=2).run(suite)
Let's place it in the same directory with web2py.py with the name testRunner.py
Now, let's place a helper file inside the gluon directory (name it test_helpers.py):
def form_postvars(tablename, fields, request, action="create", record_id=None):
"""
Creates the appropriate request vars for forms
"""
for field_name in fields:
request.vars[field_name] = fields[field_name]
if action == "create":
request.vars["_formname"] = tablename + "_" + action
elif action == "update":
request.vars["_formname"] = tablename + "_" + str(record_id)
request.vars["id"] = record_id
elif action == "delete":
request.vars["_formname"] = tablename + "_" + str(record_id)
request.vars["id"] = record_id
request.vars["delete_this_record"] = True
else:
raise Exception("The form action '", action, "' does not exist")
Now, let's create some tests. Inside our application there is a tests directory. There we create a directory called "controllers" and inside there we can put our test file for the controller. For example, here it is default.py (for a default controller)
#!/usr/bin/python
import unittest
from gluon.globals import Request, Session, Storage, Response
from gluon.contrib.test_helpers import form_postvars
class DefaultController(unittest.TestCase):
def setUp(self):
request = Request() # Use a clean request
session = Session() # Use a clean session
def testIndex(self):
form_postvars("bla", {"body": "yes"}, request, action="create", record_id=None)
resp = index()
self.assertFalse(resp['form'].errors) # do we have errors?
self.assertFalse(resp['form'].errors.has_key('name')) # is something missing?
self.assertEquals(2, len(resp["results"]))
db(db.bla.id>0).delete()
db.commit()
the name of the class should be the name of the controller we want to test and the directory it exists. For example: /controllers/appadmin.py is -> AppadminController (be careful is Controller not Controllers!).
Every function that starts with "test" is going to be executed. It is best to create tests with the same action.
form_postvars updates request.vars with the appropriate data so you can test forms.
You can call the action by it's name (index()) and the result is what the action returns as a dictionary.
Don't forget to commit to db!
You can also create a test database, just by create a model in your models directory: test_db.py
import copy
test_db = DAL('sqlite://testing.sqlite')
for tablename in db.tables: # Copy tables!
table_copy = [copy.copy(f) for f in db[tablename]]
test_db.define_table(tablename, *table_copy)
Run your test files with this command:
> python web2py.py -S testa -M -R testRunner.py
Whenever you put files inside tests/controllers or tests/models/ or test/something of your app, they'll be checked.
Notice: This is WORK IN PROGRESS! The wiki is still updated and I'll post a full example to bitbucket when I find time. Check here: http://www.google.com/url?sa=D&q=http://web2py.com/AlterEgo/default/show/260&usg=AFQjCNFlARW6FkrzPBtmmW4-XHnRjpeN4Q and http://groups.google.com/group/web2py/browse_thread/thread/e3b4ea0deccabbee/cdc6128fdca491bb?q=unit+testing&lnk=nl&
Comments (2)
0
matclab 14 years ago
0
matclab 14 years ago