Warning: Can't synchronize with repository "(default)" (Unsupported version control system "svn": No module named svn). Look in the Trac log for more information.

Version 1 (modified by Karl Guertin, 13 years ago) (diff)


Note: This document is written against rev776 on February 14, 2006 (not that it should matter)

Writing Tests

TurboGears tries to achieve good test coverage. This helps to keep bugs from becoming problems and lets developers know when they break something by changing some code that would seem to be unrelated. A patch with tests is more likely to be accepted and will generally be accepted faster than the same patch without tests.

What to test

Virtually every patch that somone creates comes with an implicit contract for its use: what parameters it takes and what its output should be. A simple example from turbogears/widgets/tests/

def test_label():
    """Tests simple labels"""
    label = widgets.Label("foo")
    rendered = label.render("The Foo")
    print rendered
    assert """<LABEL CLASS="label" FOR="foo">The Foo</LABEL>""" == rendered

This exercises the label widget's creation interface (by setting the name to 'foo'), its render method (setting the labeltext to 'The Foo') and ensures their correctness by checking the rendered output.

Most interfaces will be more complex and there will be considerably more assertions.

The other main source of tests is to exercise a bug and verify that it's fixed and remains fixed. The following test method demonstrates this (incidentally it's from the same file as the previous example):

def test_ticket272():
    """ TextFields with a "name" attribute = "title" should be OK """
    w = widgets.TableForm(fields=[widgets.TextField(name='title')])
    output = w.render().lower()
    assert 'value' not in output

How to test

Nose is an extension of the builtin python unittest module but provides additional features (such as fixtures and auto-discovery and starting the tests as soon as the first is found). For full documentation, see the nose documentation for test writing.

Nose defines a test case as any function or method starting with 'test' or 'Test'. All testing is done using the builtin python assert statement. If you have a setup_func or teardown_func fixture defined, it will be run before/after every test case.·

The only tricky part of testing comes when you're trying to test for exceptions. The following is the easiest way to do this is:

    val = Ipv4.to_python('blueberry')
    assert False, "should have raised an exception"
except Invalid, e:
    assert e.msg == Ipv4._messages['not_a_ip']