[Checkins] SVN: manuel/trunk/src/manuel/ add test isolation functionality (manuel.isolation)

Benji York benji at zope.com
Wed Jun 10 08:40:40 EDT 2009


Log message for revision 100794:
  add test isolation functionality (manuel.isolation)
  

Changed:
  A   manuel/trunk/src/manuel/isolation.py
  A   manuel/trunk/src/manuel/isolation.txt
  U   manuel/trunk/src/manuel/tests.py

-=-
Added: manuel/trunk/src/manuel/isolation.py
===================================================================
--- manuel/trunk/src/manuel/isolation.py	                        (rev 0)
+++ manuel/trunk/src/manuel/isolation.py	2009-06-10 12:40:40 UTC (rev 100794)
@@ -0,0 +1,50 @@
+import re
+import manuel
+import textwrap
+
+RESET = re.compile(r'^\.\.\s*reset-globs\s*$', re.MULTILINE)
+CAPTURE = re.compile(r'^\.\.\s*capture-globs\s*$', re.MULTILINE)
+
+baseline = {}
+
+class Reset(object):
+    pass
+
+
+def find_reset(document):
+    for region in document.find_regions(RESET):
+        document.replace_region(region, Reset())
+
+
+def execute_reset(region, document, globs):
+    if not isinstance(region.parsed, Reset):
+        return
+
+    globs.clear()
+    globs.update(baseline)
+
+
+class Capture(object):
+    pass
+
+
+def find_baseline(document):
+    # clear the baseline globs at the begining of a run (a bit of a hack)
+    baseline.clear()
+
+    for region in document.find_regions(CAPTURE):
+        document.replace_region(region, Capture())
+
+
+def execute_baseline(region, document, globs):
+    if not isinstance(region.parsed, Capture):
+        return
+
+    baseline.clear()
+    baseline.update(globs)
+
+
+class Manuel(manuel.Manuel):
+    def __init__(self):
+        manuel.Manuel.__init__(self, [find_reset, find_baseline],
+            [execute_reset, execute_baseline])


Property changes on: manuel/trunk/src/manuel/isolation.py
___________________________________________________________________
Added: svn:keywords
   + Id
Added: svn:eol-style
   + native

Added: manuel/trunk/src/manuel/isolation.txt
===================================================================
--- manuel/trunk/src/manuel/isolation.txt	                        (rev 0)
+++ manuel/trunk/src/manuel/isolation.txt	2009-06-10 12:40:40 UTC (rev 100794)
@@ -0,0 +1,106 @@
+Test Isolation
+==============
+
+One of the advantages of unittest over doctest is that the individual tests are
+isolated from one-another.
+
+In large doctests the later tests often depend on incedental details of earlier
+tests, making the tests more brittle and harder to change.
+
+Test isolation is one approach to reducing this intra-doctest coupling.
+
+Because many doctests are also `reST
+<http://docutils.sourceforge.net/rst.html>`_ documents, we'll use the reST
+comment syntax to hide our isolation indicator from any reST renderers::
+
+    .. isolate
+
+The "manuel.isolation" module provides the implementation.
+
+    >>> import manuel.isolation
+    >>> m = manuel.isolation.Manuel()
+
+All the "isolate" directive does is reset the globals in the test to an
+original setting.  Lets create a Manuel document to test isolation with:
+
+    >>> document = manuel.Document("""
+    ... We define a variable.
+    ...
+    ...     >>> x = 'hello'
+    ...
+    ... It is still defined.
+    ...
+    ...     >>> print x
+    ...     hello
+    ...     
+    ... Now we can reset the globals and it will be gone.
+    ...
+    ... .. reset-globs
+    ...
+    ...     >>> print x
+    ... """)
+
+Since the above document mixes isolation and doctests, we'll mix in the doctest
+handler.
+
+    >>> import manuel.doctest
+    >>> m.extend(manuel.doctest.Manuel())
+    >>> document.process_with(m, globs={})
+    >>> print document.formatted(),
+    File "<memory>", line 2, in <memory>
+    Failed example:
+        print x
+    Exception raised:
+        ...
+        NameError: name 'x' is not defined
+
+Of course, resetting to an empty set of global variables isn't always what's
+wanted.  In that case there is a ".. capture-globs" directive that defines a
+baseline set of globals that will be restored at each reset.
+
+
+    >>> document = manuel.Document("""
+    ... We define a variable.
+    ...
+    ...     >>> x = 'hello'
+    ...
+    ... It is still defined.
+    ...
+    ...     >>> print x
+    ...     hello
+    ...
+    ... We can capture the currently defined globals:
+    ...
+    ... .. capture-globs
+    ...
+    ... Of course capturing the globals doesn't disturb them.
+    ...
+    ...     >>> print x
+    ...     hello
+    ... 
+    ... Now if we define a new global...
+    ...
+    ...     >>> y = 'goodbye'
+    ...     >>> print y
+    ...     goodbye
+    ...
+    ... .. reset-globs
+    ...
+    ... ...it will disappear after a reset.
+    ...
+    ...     >>> print y
+    ...     
+    ... But the captured globals will still be defined.
+    ...
+    ...     >>> print x
+    ...     hello
+    ...
+    ... """)
+    >>> document.process_with(m, globs={})
+    >>> print document.formatted(),
+    File "<memory>", line 4, in <memory>
+    Failed example:
+        print y
+    Exception raised:
+        ...
+        NameError: name 'y' is not defined


Property changes on: manuel/trunk/src/manuel/isolation.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Modified: manuel/trunk/src/manuel/tests.py
===================================================================
--- manuel/trunk/src/manuel/tests.py	2009-06-10 11:57:15 UTC (rev 100793)
+++ manuel/trunk/src/manuel/tests.py	2009-06-10 12:40:40 UTC (rev 100794)
@@ -16,7 +16,8 @@
         ])
     suite = unittest.TestSuite()
 
-    tests = ['README.txt', 'footnote.txt', 'bugs.txt', 'code-block.txt']
+    tests = ['README.txt', 'footnote.txt', 'bugs.txt', 'code-block.txt',
+        'isolation.txt']
 
     # Run the tests once with doctest.
     suite.addTest(



More information about the Checkins mailing list