[Checkins] SVN: manuel/trunk/src/manuel/README.txt add an example of enhancing pre-existing test handling

Benji York benji at zope.com
Sat Jun 13 14:19:08 EDT 2009


Log message for revision 100921:
  add an example of enhancing pre-existing test handling
  

Changed:
  U   manuel/trunk/src/manuel/README.txt

-=-
Modified: manuel/trunk/src/manuel/README.txt
===================================================================
--- manuel/trunk/src/manuel/README.txt	2009-06-13 17:26:42 UTC (rev 100920)
+++ manuel/trunk/src/manuel/README.txt	2009-06-13 18:19:08 UTC (rev 100921)
@@ -426,3 +426,141 @@
      ('clone: 1, 2, 3\n', 'cloned to go before'),
      ("\nI want some copies of my clone.\n\nFor example, I'd like a clone before *here*.\n\nI'd also like a clone after *here*.\n", None),
      ('clone: 1, 2, 3\n', 'cloned to go after')]
+
+
+Enhancing Existing Manuels
+--------------------------
+
+Lets say that you'd like failed doctest examples to give more information about
+what went wrong.
+
+First we'll create an evaluater that includes pertinant variable binding
+information on failures.
+
+    >>> import doctest
+
+    >>> def informative_evaluater(region, document, globs):
+    ...     if not isinstance(region.parsed, doctest.Example):
+    ...         return
+    ...     if region.evaluated.getvalue():
+    ...         info = ''
+    ...         for name in sorted(globs):
+    ...             if name in region.parsed.source:
+    ...                 info += '\n    ' + name + ' = ' + repr(globs[name])
+    ...
+    ...         if info:
+    ...             region.evaluated.write('Additional Information:')
+    ...             region.evaluated.write(info)
+
+To do that we'll start with an instance of manuel.doctest.Manuel and add in our
+additional functionality.
+
+    >>> m = manuel.doctest.Manuel()
+    >>> m.add_evaluater(informative_evaluater)
+
+Now we'll create a document that includes a failing test.
+
+    >>> document = manuel.Document("""
+    ... Set up some variable bindings:
+    ...
+    ...     >>> a = 1
+    ...     >>> b = 2
+    ...     >>> c = 3
+    ...
+    ... Make an assertion:
+    ...
+    ...     >>> a + b
+    ...     5
+    ... """)
+
+    >>> document.process_with(m, globs={})
+    >>> print document.formatted()
+    File "<memory>", line 10, in <memory>
+    Failed example:
+        a + b
+    Expected:
+        5
+    Got:
+        3
+    Additional Information:
+        a = 1
+        b = 2
+
+Note how only the referenced variable bindings are displayed (i.e., "c" is not
+listed).  That's pretty nice, but the way interesting variables are identified
+is a bit of a hack.  For example, if a variable's name just happens to appear
+in the source (in a comment for example), it will be included in the output:
+
+    >>> document = manuel.Document("""
+    ... Set up some variable bindings:
+    ...
+    ...     >>> a = 1
+    ...     >>> b = 2
+    ...     >>> c = 3
+    ...
+    ... Make an assertion:
+    ...
+    ...     >>> a + b # doesn't mention "c"
+    ...     5
+    ... """)
+
+    >>> document.process_with(m, globs={})
+    >>> print document.formatted()
+    File "<memory>", line 10, in <memory>
+    Failed example:
+        a + b # doesn't mention "c"
+    Expected:
+        5
+    Got:
+        3
+    Additional Information:
+        a = 1
+        b = 2
+        c = 3
+
+Instead of a text-based apprach, lets use the built-in tokenize module to more
+robustly identify referenced variables.
+
+    >>> import StringIO
+    >>> import token
+    >>> import tokenize
+
+    >>> def informative_evaluater_2(region, document, globs):
+    ...     if not isinstance(region.parsed, doctest.Example):
+    ...         return
+    ...
+    ...     reader = StringIO.StringIO(region.source).readline
+    ...
+    ...     if region.evaluated.getvalue():
+    ...         vars = []
+    ...         for ttype, tval, _, _, _ in tokenize.generate_tokens(reader):
+    ...             if ttype == token.NAME:
+    ...                 vars.append(tval)
+    ...
+    ...         info = ''
+    ...         for name in sorted(globs):
+    ...             if name in vars:
+    ...                 info += '\n    ' + name + ' = ' + repr(globs[name])
+    ...
+    ...         if info:
+    ...             region.evaluated.write('Additional Information:')
+    ...             region.evaluated.write(info)
+
+    >>> m = manuel.doctest.Manuel()
+    >>> m.add_evaluater(informative_evaluater_2)
+
+Now when we have a failure, only the genuinely referenced variables will be
+included in the debugging information.
+
+    >>> document.process_with(m, globs={})
+    >>> print document.formatted()
+    File "<memory>", line 10, in <memory>
+    Failed example:
+        a + b # doesn't mention "c"
+    Expected:
+        5
+    Got:
+        3
+    Additional Information:
+        a = 1
+        b = 2



More information about the Checkins mailing list