|Version 1 (modified by Karl Guertin, 11 years ago) (diff)|
Note: This document is written against rev776 on February 14, 2006 (not that it should matter)
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/test_widgets.py:
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:
try: val = Ipv4.to_python('blueberry') assert False, "should have raised an exception" except Invalid, e: assert e.msg == Ipv4._messages['not_a_ip']