Version 109 (modified by Mike A, 13 years ago) ( diff )

Added notes on unit tests and test command instructions


"A bug is a test case you haven't written yet"
"Unit Tests allow merciless refactoring"

As it is a disaster management tool, bugs in Sahana that lead to aid/rescue workers in the field receiving incorrect or incomplete information could potentially lead to disaster victims losing their lives. Therefore, Sahana developers need to place more emphasis on testing than might be required in other types of projects.

This page defines what our current approach versus our BluePrint for future options

Test-Driven Development is a programming styles which says that you 1st write your test cases (from the specs) & then proceed to make them pass.

For manual tests, can pre-populate the database with random data using gluon.contrib.populate

Functional Tests

Building the Right Code

We have integrated into /static/selenium so that Functional Tests can be run easily. For Notes on how to create your own test cases see CreatingTestCasesFirst.

Tests can be developed using Selenium IDE, if desired.

See the Documentation for details on how to use this test suite.


  • Some wrapper scripts for Win32 attached
  • Improving the stability of Selenium tests:
  • Lots of useful tips:
  • Autocomplete is fiddly to test as need to trigger specific events:
    # Enter the search String
    sel.type("gis_location_autocomplete", "SearchString")
    # Trigger the event to get the AJAX to send
    sel.fire_event("gis_location_autocomplete", "keydown")
    # Wait for the popup menu
    for i in range(60):
            if "SearchString" == sel.get_text("css=ul.ui-autocomplete li:first-child a"):
    else:"time out")
    # Select the Result
    sel.fire_event("css=ul.ui-autocomplete li:first-child a", "mouseover")"css=ul.ui-autocomplete li:first-child a")

Systers' approach:

Alternative Options:

Unit Tests

"Building the Code Right"

Unit tests test the system at the level of units of source code a.k.a. code blocks. Not to be confused with functional or acceptance/customer tests; unit tests verify rather than validate.


  • stability and reliability - vital for scaling developer teams due to the need for a stable trunk,
  • self documenting system - with documentation that can't drift.
  • simplification of integration testing (because all the parts are known to work, only interfaces between them need testing),
  • better system design by:
  • * easing refactoring (changes can be more rapidly verified not to create new bugs),
  • * promoting refactoring (dividing units into testable pieces also creates more reusable pieces),
  • * standing in for specification documents (i.e. describing by example what the code needs to do).


  • it takes time to develop and maintain the tests - which means sloppy tests are as bad or worse than sloppy code.

Test Runner

Web2py imposes a severe problem on any external test runner, i.e. application code is provided a global environment by web2py, it must expect that environment. Therefore, the test runner must reproduce and provide that environment to the tests. This means that we can't use any external test runner that doesn't know about web2py.

nose is a python module/command which finds and runs tests. nose is suitable as it has been widely adopted in the python community, allows standard test specifications and is highly configurable and customisable, without confusing "magical" behaviour. To work with web2py, a plugin has been written, which means that nosetests isn't run in the normal way, although we'll aim for that as much as possible.

To run the unit tests in Sahana Eden via nose, there is a command in the tests/ folder within the application. Note: This command is not installed outside of the application as it is designed for developers, who may have several versions of Sahana Eden at any one time.


Assume our current directory is web2py/, which contains the applications folder.

To run all unit tests: ./application/trunk/tests/

Currently these tests are stored in /tests. The nose plugin will look for tests in this folder. To select tests, give a file or folder path relative to the tests folder.

For example, there is a gis folder containing tests for the GIS mapping code. To run these particular tests: ./application/trunk/tests/ gis

Particular python version. runs the tests with whichever python version ran it. It will use /usr/bin/python if run as an ordinary command as above. To select a different python version run (e.g. python 2.5): /path/to/python2.5 ./application/trunk/tests/

This may be useful to test different versions but also installed modules. N.B. No testing has been done with virtualenv as of this time.

Javascript unit tests

Selenium enables functional testing but not really unit testing other than reporting the results of javascript test runs.

Selenium RC is great due to ability to handle JavaScript & also due to having an IDE for generating them (export as Python).
The IDE output needs to be modified to work with Web2Py.
NB Custom functions (e.g. for Random) cannot be shared with the Functional Tests (custom=JS) but the rest of the tests can be.
ToDo: Port the storeRandom function from JS to Python:

import random
print "test_%i@xxxxxxxx" % random.randint(1, 10000)

CherryPy's WebTest is good for in-process testing & can be run from a browser-less server(easier for CI-integration).
These tests are stored in /tests/webtest.
NB These are a work-in-progress...need to enable access to Web2Py environment (db, etc) using:

from import exec_environment

Or could write as a 'Controller' & call from CLI:

python -S appname -M -R 

Another similar option could be Pylon's WebTest

Doc Tests

Agile documentation which can be run using Web2Py's Admin UI.

To extend these to web applications, we have a module which uses wsgi_intercept & CherryPy's WebTest: modules/s3/
This can be used from Controllers like:

def login():
    """ Login
    >>> from applications.sahana.modules.s3.s3test import WSGI_Test
    >>> test=WSGI_Test(db)
    >>> '200 OK' in test.getPage('/sahana/%s/login' % module)
    >>> test.assertHeader("Content-Type", "text/html")
    >>> test.assertInBody('Login')

This works fine,although if an assert fails then the UI gets stuck :/
The 'db' access part isn't yet working.

Note that Web2Py uses a big doctest at the end of each file: def test_all()

Continuous Integration

We are starting to use Jenkins to run the Functional Tests automatically.

Other options:



Attachments (4)

Download all attachments as: .zip

Note: See TracWiki for help on using the wiki.