Unit Tests als DocTests schreiben
DocTests als Unit Tests haben den Vorteil, dass sie direkt in docstrings beim auszuführenden Code stehen. Darüberhinaus bietet die Syntax von DocTests viele Annehmlichkeiten, die das Schreiben von Tests angenehmer und schneller machen.
Im folgenden zeige ich ein einfaches Beispiel aus Archetypes:
[...]
class ReferenceSource(object):
"""A base implementation of an IReferenceSource adapter that
relies on a IReferenceQuery local utility to look up targets and
on an IReferenceStorage adapter to add references.
Basic setup:
>>> import archetypes.testing
>>> archetypes.testing.setupPortal()
>>> archetypes.testing.wireUp()
We create an object that we adapt to our ReferenceSource:
>>> obj = archetypes.testing.FakeObject('sourceobj')
>>> source = ReferenceSource(obj)
We don't have any targets or relationships at this point:
>>> source.getTargets()
[]
>>> source.getRelationships()
set([])
[...]
Teardown:
>>> archetypes.testing.teardownPortal()
"""
[...]
Der Test Runner schaut nach DocTests innerhalb von docstrings, und führt jeden von ihnen als seine eigene Test Fixture, d.h. unabhängig von anderen Tests, aus. In diesem Beispiel werden Tests für jede Klasse geschrieben, die zugleich dokumentieren, wie die Klasse verwendet wird.
docstring DocTests ausführen
Um docstring-DocTests ausführen zu können, muss noch eine Test Suite hinzugefügt werden, die dem Test Runner sagt, dass er nach diesen docstrings suchen soll. In den meisten Fällen genügt eine einfache Test Suite, die das Zope-3-Framework nutzt, wie z.B. test_doctests.py, die auf die o.g. base.py referenziert:
import unittest
from zope.testing import doctest
optionflags = doctest.REPORT_ONLY_FIRST_FAILURE | doctest.ELLIPSIS
def test_suite():
from zope.testing.doctestunit import DocTestSuite
return unittest.TestSuite((
DocTestSuite('archetypes.reference.base',
optionflags=optionflags),
))
if __name__ == '__main__':
unittest.main(defaultTest='test_suite')
Wenn Sie PloneTestCase benötigen, sieht Ihre Test Suite z.B. so aus:
import unittest
from zope.testing import doctest
from Testing.ZopeTestCase import ZopeDocTestSuite
from Products.pluggablecatalog.tests import common
common.setupPloneSite()
from Products.PloneTestCase import PloneTestCase
optionflags = (doctest.ELLIPSIS |
doctest.NORMALIZE_WHITESPACE |
doctest.REPORT_ONLY_FIRST_FAILURE)
def test_suite():
return unittest.TestSuite(
[ZopeDocTestSuite(module,
test_class=PloneTestCase.PloneTestCase,
optionflags=optionflags)
for module in ('Products.pluggablecatalog.tool',)]
)
Diese Test Suite ist testDoctests des pluggablecatalog-Produkts entnommen.
Und common enthält einfach:
def setupPloneSite():
from Products.PloneTestCase import PloneTestCase
PloneTestCase.installProduct('pluggablecatalog')
PloneTestCase.setupPloneSite()