[Checkins] SVN: manuel/trunk/ - many more docs updates
Benji York
benji at zope.com
Fri Jun 19 17:55:17 EDT 2009
Log message for revision 101155:
- many more docs updates
- bug fixes
Changed:
U manuel/trunk/buildout.cfg
A manuel/trunk/src/getting-started.txt
U manuel/trunk/src/index.txt
U manuel/trunk/src/intro.txt
U manuel/trunk/src/manuel/README.txt
U manuel/trunk/src/manuel/__init__.py
U manuel/trunk/src/manuel/bugs.txt
U manuel/trunk/src/manuel/codeblock.py
U manuel/trunk/src/manuel/codeblock.txt
A manuel/trunk/src/manuel/doctest.txt
U manuel/trunk/src/manuel/footnote.txt
A manuel/trunk/src/manuel/ignore.py
A manuel/trunk/src/manuel/ignore.txt
U manuel/trunk/src/manuel/isolation.txt
U manuel/trunk/src/manuel/table-example.txt
U manuel/trunk/src/manuel/testing.py
U manuel/trunk/src/manuel/tests.py
-=-
Modified: manuel/trunk/buildout.cfg
===================================================================
--- manuel/trunk/buildout.cfg 2009-06-19 20:56:53 UTC (rev 101154)
+++ manuel/trunk/buildout.cfg 2009-06-19 21:55:17 UTC (rev 101155)
@@ -58,4 +58,4 @@
zc.recipe.egg = 1.2.2
zc.recipe.testrunner = 1.2.0
zope.interface = 3.5.1
-zope.testing = 3.7.4
+zope.testing = 3.7.5
Added: manuel/trunk/src/getting-started.txt
===================================================================
--- manuel/trunk/src/getting-started.txt (rev 0)
+++ manuel/trunk/src/getting-started.txt 2009-06-19 21:55:17 UTC (rev 101155)
@@ -0,0 +1,56 @@
+Getting Started
+===============
+
+The simplest way to get started with Manuel is to create a script to run your
+tests, like so:
+
+.. code-block:: python
+
+ import manuel.codeblock
+ import manuel.doctest
+ import manuel.testing
+ import unittest
+
+ def test_suite():
+ m = manuel.doctest.Manuel()
+ m.extend(manuel.codeblock.Manuel())
+ return manuel.testing.TestSuite(m, 'test-one.txt', 'test-two.txt')
+
+ if __name__ == '__main__':
+ unittest.TextTestRunner().run(test_suite())
+
+
+Using zope.testing
+------------------
+
+If you want to use zope.testing's test runner (usable stand-alone, it isn't
+dependent on the Zope application server), you can add Manuel tests to the
+TestSuite objects you're already creating.
+
+.. code-block:: python
+
+ import manuel.codeblock
+ import manuel.doctest
+ import manuel.testing
+
+ def test_suite():
+ suite = unittest.TestSuite()
+
+ # here you add your other tests to the suite...
+
+ # now you can add the Manuel tests
+ m = manuel.doctest.Manuel()
+ m.extend(manuel.codeblock.Manuel())
+ suite.addTest(manuel.testing.TestSuite(m,
+ 'test-one.txt', 'test-two.txt'))
+
+ return suite
+
+
+Others
+------
+
+If you know how to make Manuel work with other test runners, please `send me an
+email`_.
+
+.. _send me an email: benji+manuel at benjiyork.com
Property changes on: manuel/trunk/src/getting-started.txt
___________________________________________________________________
Added: svn:eol-style
+ native
Modified: manuel/trunk/src/index.txt
===================================================================
--- manuel/trunk/src/index.txt 2009-06-19 20:56:53 UTC (rev 101154)
+++ manuel/trunk/src/index.txt 2009-06-19 21:55:17 UTC (rev 101155)
@@ -7,9 +7,12 @@
:numbered:
intro.txt
- manuel/README.txt
- manuel/table-example.txt
+ getting-started.txt
manuel/codeblock.txt
+ manuel/doctest.txt
manuel/footnote.txt
+ manuel/ignore.txt
manuel/isolation.txt
+ manuel/README.txt
+ manuel/table-example.txt
manuel/bugs.txt
Modified: manuel/trunk/src/intro.txt
===================================================================
--- manuel/trunk/src/intro.txt 2009-06-19 20:56:53 UTC (rev 101154)
+++ manuel/trunk/src/intro.txt 2009-06-19 21:55:17 UTC (rev 101155)
@@ -1,27 +1,35 @@
Introduction
============
-Manuel lets you mix and match traditional doctests with new test syntax that
-either you create or comes bundled with Manuel.
+Manuel lets you mix and match traditional doctests with custom test syntax.
+Several plug-ins that provide new syntaxes are included. You can also make
+your own.
+
For example, if you've ever wanted to include a large chunk of Python in a
doctest but were irritated by all the ">>>" and "..." prompts required, you'd
-like the "manuel.codeblock" module. It lets you execute code using
-Sphinx-style ".. code-block:: python" directives, like so:
+like the :mod:`manuel.codeblock` module. It lets you execute code using
+Sphinx-style ".. code-block:: python" directives. The markup looks like
+this::
-.. code-block:: python
+ .. code-block:: python
- import foo
+ import foo
- def my_func(bar):
- return foo.baz(bar)
+ def my_func(bar):
+ return foo.baz(bar)
-Incidentally, the implementation of manuel.codeblock is only 24 lines of code.
+Incidentally, the implementation of :mod:`manuel.codeblock` is only 22 lines of
+code.
-For an example of creating your own test syntax, take a look at the
+For a large example of creating test syntax, take a look at the
:ref:`fit-table-example` or for all the details, :ref:`theory-of-operation`.
+Also, the plug-ins included in Manuel make good examples while being quite
+useful in their own right. All the included plug-ins are listed in the next
+section.
+
Included Functionality
======================
@@ -30,15 +38,15 @@
:ref:`manuel.codeblock <code-blocks>`
executes code in ".. code-block:: python" blocks
+:ref:`manuel.doctest <doctest>`
+ provides traditional doctest processing as a Manuel plug-in
+
:ref:`manuel.footnote <footnotes>`
executes code in reST-style footnodes each time they're referenced (good
for getting incedental code out of the main flow of a document)
+:ref:`manuel.ignore <ignore>`
+ ignores parts of a document while running tests
+
:ref:`manuel.isolation <isolation>`
makes it easier to have test isolation in doctests
-
-
-Getting Started
-===============
-
-If you already have XXX
Modified: manuel/trunk/src/manuel/README.txt
===================================================================
--- manuel/trunk/src/manuel/README.txt 2009-06-19 20:56:53 UTC (rev 101154)
+++ manuel/trunk/src/manuel/README.txt 2009-06-19 21:55:17 UTC (rev 101155)
@@ -4,7 +4,7 @@
===================
Manuel parses documents (tests), evaluates their contents, then formats the
-result of the evaluation. The functionality is accessed via the "manuel"
+result of the evaluation. The functionality is accessed via the :mod:`manuel`
package.
>>> import manuel
@@ -93,11 +93,6 @@
.. more "whole-line" tests.
- >>> document.find_regions('three')
- Traceback (most recent call last):
- ...
- ValueError: Regions must end at the ending of a line.
-
>>> document.find_regions(
... re.compile('ne:.*$', re.MULTILINE),
... re.compile('^one:.*$', re.MULTILINE),
@@ -106,14 +101,6 @@
...
ValueError: Regions must start at the begining of a line.
- >>> document.find_regions(
- ... re.compile('^one:.*$', re.MULTILINE),
- ... re.compile('^three:', re.MULTILINE),
- ... )
- Traceback (most recent call last):
- ...
- ValueError: Regions must end at the ending of a line.
-
Now we can register a parser that will identify the regions we're interested in
and create NumbersTest objects from the source text.
@@ -176,7 +163,7 @@
----------
Once the evaluation phase is completed the results are formatted. You guessed
-it: manuel provides a method for formatting results. We'll build one to format
+it: Manuel provides a method for formatting results. We'll build one to format
a message about whether or not our lists of numbers are sorted properly. A
formatting function returns None when it has no output, or a string otherwise.
@@ -224,8 +211,8 @@
... """
>>> document = manuel.Document(source)
-The manuel.doctest module has handlers for the various phases. First we'll
-look at parsing.
+The :mod:`manuel.doctest` module has handlers for the various phases. First
+we'll look at parsing.
>>> import manuel.doctest
>>> m = manuel.doctest.Manuel()
@@ -309,7 +296,7 @@
Combining Test Types
--------------------
-Now that we have both doctests and the silly "sorted numbers" tests, lets
+Now that we have both doctests and the silly "sorted numbers" tests, let's
create a single document that has both.
>>> document = manuel.Document("""
@@ -453,8 +440,8 @@
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.
+To do that we'll start with an instance of :mod:`manuel.doctest.Manuel` and add
+in our additional functionality.
>>> m = manuel.doctest.Manuel()
>>> m.add_evaluater(informative_evaluater)
@@ -522,7 +509,7 @@
b = 2
c = 3
-Instead of a text-based apprach, lets use the built-in tokenize module to more
+Instead of a text-based apprach, let's use the built-in tokenize module to more
robustly identify referenced variables.
>>> import StringIO
Modified: manuel/trunk/src/manuel/__init__.py
===================================================================
--- manuel/trunk/src/manuel/__init__.py 2009-06-19 20:56:53 UTC (rev 101154)
+++ manuel/trunk/src/manuel/__init__.py 2009-06-19 21:55:17 UTC (rev 101155)
@@ -70,7 +70,7 @@
def check_region_end(region, match):
if match.end() != len(region.source) \
- and region.source[match.end()] != '\n':
+ and region.source[match.end()-1] != '\n':
raise ValueError(
'Regions must end at the ending of a line.')
@@ -124,6 +124,12 @@
return sorted(handlers, key=key)
+def find_end_of_line(s):
+ end = 0
+ while len(s) < end and s[end] != '\n':
+ end += 1
+ return end
+
class Document(object):
def __init__(self, source, location='<memory>'):
@@ -155,7 +161,7 @@
if end is None:
end_match = None
- check_region_end(region, start_match)
+
text = start_match.group()
else:
end_match = end.search(region.source, start_match.end())
@@ -163,8 +169,9 @@
# couldn't find a match for the end re, try again
if end_match is None:
continue
- check_region_end(region, end_match)
- text = region.source[start_match.start():end_match.end()]
+ end_position = end_match.end() + \
+ find_end_of_line(region.source[end_match.end():])
+ text = region.source[start_match.start():end_position]
if text[-1] != '\n':
text += '\n'
Modified: manuel/trunk/src/manuel/bugs.txt
===================================================================
--- manuel/trunk/src/manuel/bugs.txt 2009-06-19 20:56:53 UTC (rev 101154)
+++ manuel/trunk/src/manuel/bugs.txt 2009-06-19 21:55:17 UTC (rev 101155)
@@ -1,6 +1,17 @@
Fixed Bugs
==========
+Here are demonstrations of various bugs that have been fixed in Manuel. If you
+encounter a bug in a previous version of Manuel, check here in the newest
+version to see if your bug has been addressed.
+
+This document is likely only interesting to people using creating their own
+plug-ins.
+
+
+Start and End Coinciding
+------------------------
+
If a line of text matches both a "start" and "end" regular expression, no
exception should be raised.
Modified: manuel/trunk/src/manuel/codeblock.py
===================================================================
--- manuel/trunk/src/manuel/codeblock.py 2009-06-19 20:56:53 UTC (rev 101154)
+++ manuel/trunk/src/manuel/codeblock.py 2009-06-19 21:55:17 UTC (rev 101155)
@@ -2,16 +2,13 @@
import manuel
import textwrap
-CODEBLOCK_START = re.compile(
- r'(?<=\n\n)\.\.\s*code-block::?\s*python\s*\n', re.DOTALL)
+# XXX document code-blocks that are really comments but get executed anyway
+# (perhaps with better syntax)
-# XXX document code-blocks that don't get executed and code-blocks that are
-# really comments but get executed anyway (perhaps with better syntax for both)
+CODEBLOCK_START = re.compile(r'^\.\.\s*code-block::?\s*python\b', re.MULTILINE)
+CODEBLOCK_END = re.compile(r'(\n\Z|\n(?=\S))')
-# XXX should probably take end-of-file into account
-CODEBLOCK_END = re.compile(r'^\S.*$', re.MULTILINE)
-
class CodeBlock(object):
def __init__(self, code):
self.code = code
@@ -19,7 +16,7 @@
def find_code_blocks(document):
for region in document.find_regions(CODEBLOCK_START, CODEBLOCK_END):
- source = textwrap.dedent('\n'.join(region.source.splitlines()[1:-1]))
+ source = textwrap.dedent('\n'.join(region.source.splitlines()[1:]))
source_location = '%s:%d' % (document.location, region.lineno)
code = compile(source, source_location, 'exec', 0, True)
document.replace_region(region, CodeBlock(code))
@@ -29,8 +26,7 @@
if not isinstance(region.parsed, CodeBlock):
return
- code = region.parsed.code
- exec code in globs
+ exec region.parsed.code in globs
del globs['__builtins__'] # exec adds __builtins__, we don't want it
Modified: manuel/trunk/src/manuel/codeblock.txt
===================================================================
--- manuel/trunk/src/manuel/codeblock.txt 2009-06-19 20:56:53 UTC (rev 101154)
+++ manuel/trunk/src/manuel/codeblock.txt 2009-06-19 21:55:17 UTC (rev 101155)
@@ -15,13 +15,13 @@
print 'hello'
-The manuel.codeblock module provides the ability to execute the contents of
-Python code-blocks.
+The :mod:`manuel.codeblock` module provides the ability to execute the contents
+of Python code-blocks.
>>> import manuel.codeblock
>>> m = manuel.codeblock.Manuel()
-Let's create a reST document with a code block.
+.. Let's create a reST document with a code block.
>>> document = manuel.Document("""
... Here is a code-block:
@@ -34,13 +34,83 @@
...
... >>> print x
... hello
- ...
+ ...
... """)
-Since the above document mixes code-blocks and doctests, we'll mix in the
-doctest handler.
+.. Since the above document mixes code-blocks and doctests, we'll mix in the
+ doctest handler.
>>> import manuel.doctest
>>> m.extend(manuel.doctest.Manuel())
>>> document.process_with(m, globs={})
+
+.. Both code blocks were found (for a total of five regions -- text, block,
+ text, block, and text):
+
+ >>> len(list(document))
+ 5
+
+.. We can see that none of the tests in the document failed:
+
>>> print document.formatted(),
+
+If the code-block generates some sort of error...
+
+ >>> document = manuel.Document("""\
+ ... .. code-block:: python
+ ...
+ ... print does_not_exist
+ ... """)
+
+.. the document above was specially formulated to have nothing before or after
+ the code-block
+
+ >>> document.source.startswith('.. code-block')
+ True
+ >>> document.source.endswith('print does_not_exist\n')
+ True
+
+...that error will be reported:
+
+ >>> document.process_with(m, globs={})
+ Traceback (most recent call last):
+ ...
+ NameError: name 'does_not_exist' is not defined
+
+If you find that you want to include a code-block in a document but don't want
+Manuel to execute it, use :ref:`manuel.ignore <ignore>` to ignore that
+particular block.
+
+
+Commented-out Blocks
+--------------------
+
+At times you'll want to have a block of code that is executed but not displayed
+in the rendered document (like some setup for later examples).
+
+When using doctest's native format (">>>") that's easy to do, you just put the
+code in a reST comment, like so:
+
+.. ignore-next-block
+
+::
+
+ .. this is some setup, it is hidden in a reST comment
+
+ >>> do_something()
+ >>> do_something_else()
+
+However, if you want to include a relatively large chunk of Python, you'd
+rather use a code-block, but that means that it will be included in the
+rendered document. Instead, :mod:`manuel.codeblock` also understands a variant
+of the code-block directive (".. code-block:: python") that is actually a reST
+comment: ".. code-block:python" (note the single colon)::
+
+ .. code-block: python
+
+ do_something()
+ do_something_else()
+
+.. warning:: It would be very easy to confuse the "real" code-block directive
+ with the it's-really-a-reSt-comment form. Perhaps a more distinct syntax
+ will be introduced in the future.
Added: manuel/trunk/src/manuel/doctest.txt
===================================================================
--- manuel/trunk/src/manuel/doctest.txt (rev 0)
+++ manuel/trunk/src/manuel/doctest.txt 2009-06-19 21:55:17 UTC (rev 101155)
@@ -0,0 +1,50 @@
+.. _doctest:
+
+Doctests
+========
+
+Manuel is all about making testable documents and well-documented tests. Of
+course, Python's doctest module is a long-standing fixture in that space, so it
+only makes sense for Manuel to support doctest syntax.
+
+Handling doctests is easy:
+
+.. code-block:: python
+
+ import manuel.doctest
+
+ m = manuel.doctest.Manuel()
+ suite = manuel.testing.TestSuite(m, 'my-doctest.txt')
+
+Of course you can mix in other Manuel syntax plug-ins as well (including ones
+you write yourself).
+
+.. code-block:: python
+
+ import manuel.doctest
+ import manuel.codeblock
+
+ m = manuel.doctest.Manuel()
+ m.extend(manuel.codeblock.Manuel())
+ suite = manuel.testing.TestSuite(m, 'my-doctest-with-code-blocks.txt')
+
+The :class:`manuel.doctest.Manuel` constructor also takes :data:`optionflags`
+and :data:`checker` arguments.
+
+.. code-block:: python
+
+ m = manuel.doctest.Manuel(optionflags=optionflags, checker=checker)
+
+See the `doctest documentation <http://docs.python.org/library/doctest.html>`_
+for more information about the `available options
+<http://docs.python.org/library/doctest.html#doctest-options>`_ and `output
+checkers <http://docs.python.org/library/doctest.html#outputchecker-objects>`_
+
+
+.. note:: :mod:`zope.testing.renormalizing` provides an :class:`OutputChecker`
+ for smoothing out differences between actual and expected output for things
+ that are hard to control (like memory addresses and time) using regular
+ expressions. See the `module's doctests
+ <http://svn.zope.org/zope.testing/trunk/src/zope/testing/renormalizing.py?view=markup>`_
+ for more information on how it works.
+
Property changes on: manuel/trunk/src/manuel/doctest.txt
___________________________________________________________________
Added: svn:eol-style
+ native
Modified: manuel/trunk/src/manuel/footnote.txt
===================================================================
--- manuel/trunk/src/manuel/footnote.txt 2009-06-19 20:56:53 UTC (rev 101154)
+++ manuel/trunk/src/manuel/footnote.txt 2009-06-19 21:55:17 UTC (rev 101155)
@@ -4,7 +4,7 @@
Footnotes
=========
-The manuel.footnote module provides an implementation of reST footnote
+The :mod:`manuel.footnote` module provides an implementation of reST footnote
handling.
>>> import manuel.footnote
@@ -38,17 +38,12 @@
...
... >>> raise RuntimeError('nooooo!')
... """)
-
>>> document.process_with(m, globs={})
Since all the examples in the doctest above are correct, we expect no errors.
- >>> for region in document:
- ... if region.formatted:
- ... print '-'*70
- ... print region.formatted,
+ >>> print document.formatted(),
-
The order of examples in footnotes is preserved. If not, the document below
will generate an error because "a" won't be defined when "b = a + 1" is
evaluated.
Added: manuel/trunk/src/manuel/ignore.py
===================================================================
--- manuel/trunk/src/manuel/ignore.py (rev 0)
+++ manuel/trunk/src/manuel/ignore.py 2009-06-19 21:55:17 UTC (rev 101155)
@@ -0,0 +1,17 @@
+import re
+import manuel
+import textwrap
+
+IGNORE_START = re.compile(r'^\.\.\s*ignore-next-block\s*$', re.MULTILINE)
+IGNORE_END = re.compile(r'(?<!ignore-next-block)\n\n(?=\S)|\Z')
+
+baseline = {}
+
+def find_ignores(document):
+ for region in document.find_regions(IGNORE_START, IGNORE_END):
+ document.replace_region(region, None)
+ document.remove_region(region)
+
+class Manuel(manuel.Manuel):
+ def __init__(self):
+ manuel.Manuel.__init__(self, [find_ignores])
Property changes on: manuel/trunk/src/manuel/ignore.py
___________________________________________________________________
Added: svn:keywords
+ Id
Added: svn:eol-style
+ native
Added: manuel/trunk/src/manuel/ignore.txt
===================================================================
--- manuel/trunk/src/manuel/ignore.txt (rev 0)
+++ manuel/trunk/src/manuel/ignore.txt 2009-06-19 21:55:17 UTC (rev 101155)
@@ -0,0 +1,104 @@
+.. _ignore:
+
+Ignoring Blocks
+===============
+
+Occasionally the need arrises to ignore a block of markup that would otherwise
+be parsed by a Manuel plug-in.
+
+For example, this document has a code-block will generate a Syntax error:
+
+ >>> import manuel
+ >>> document = manuel.Document("""
+ ... The following is invalid Python.
+ ...
+ ... .. code-block:: python
+ ...
+ ... def foo:
+ ... pass
+ ...
+ ... """)
+
+We can see that when executed, the SyntaxError escapes.
+
+ >>> import manuel.codeblock
+ >>> m = manuel.codeblock.Manuel()
+ >>> document.process_with(m, globs={})
+ Traceback (most recent call last):
+ ...
+ File "<memory>:4", line 2
+ def foo:
+ ^
+ SyntaxError: invalid syntax
+
+The :mod:`manuel.ignore` module provides a way to ignore parts of a document
+using a directive ".. ignore-next-block".
+
+Because Manuel plug-ins are executed in the order they are accumulated, we want
+:mod:`manuel.ignore` to be the base Manuel object, with any others added to it.
+
+.. code-block:: python
+
+ import manuel.ignore
+ import manuel.doctest
+ m = manuel.ignore.Manuel()
+ m.extend(manuel.codeblock.Manuel())
+ m.extend(manuel.doctest.Manuel())
+
+If we add an ignore marker to the block we don't want processed...
+
+.. code-block:: python
+
+ >>> document = manuel.Document("""
+ ... The following is invalid Python.
+ ...
+ ... .. ignore-next-block
+ ... .. code-block:: python
+ ...
+ ... def foo:
+ ... pass
+ ... """)
+
+...the error goes away.
+
+ >>> document.process_with(m, globs={})
+ >>> print document.formatted(),
+
+
+Ignoring Literal Blocks
+-----------------------
+
+Ignoring literal blocks is a little more involved:
+
+ >>> document = manuel.Document("""
+ ... Here is some invalid Python:
+ ...
+ ... .. ignore-next-block
+ ...
+ ... ::
+ ...
+ ... >>> lambda: print 'hi'
+ ... """)
+
+.. no need for this bit to be visible in the docs
+
+ >>> document.process_with(m, globs={})
+ >>> print document.formatted(),
+
+.. we want to be very sure that the above example without the ignore actually
+ generates an error:
+
+ >>> document = manuel.Document(document.source.replace(
+ ... '.. ignore-next-block', ''))
+ >>> document.process_with(m, globs={})
+ >>> print document.formatted(),
+ File "<memory>", line 8, in <memory>
+ Failed example:
+ lambda: print 'hi'
+ Exception raised:
+ ...
+ File "<doctest <memory>[0]>", line 1
+ lambda: print 'hi'
+ ^
+ SyntaxError: invalid syntax
+
Property changes on: manuel/trunk/src/manuel/ignore.txt
___________________________________________________________________
Added: svn:eol-style
+ native
Modified: manuel/trunk/src/manuel/isolation.txt
===================================================================
--- manuel/trunk/src/manuel/isolation.txt 2009-06-19 20:56:53 UTC (rev 101154)
+++ manuel/trunk/src/manuel/isolation.txt 2009-06-19 21:55:17 UTC (rev 101155)
@@ -9,21 +9,14 @@
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.
+Test isolation is one approach to reducing this intra-doctest coupling. The
+:mod:`manuel.isolation` module provides a plug-in to help.
-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:
+The ".. reset-globs" directive resets the globals in the test. Let's create a
+Manuel document to test isolation with:
>>> document = manuel.Document("""
... We define a variable.
@@ -47,6 +40,10 @@
>>> import manuel.doctest
>>> m.extend(manuel.doctest.Manuel())
+
+We can see that after the globals have been reset, the "print x" line raises an
+error.
+
>>> document.process_with(m, globs={})
>>> print document.formatted(),
File "<memory>", line 2, in <memory>
@@ -57,7 +54,7 @@
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
+wanted. In that case there is a ".. capture-globs" directive that saves a
baseline set of globals that will be restored at each reset.
@@ -91,6 +88,9 @@
... ...it will disappear after a reset.
...
... >>> print y
+ ... Traceback (most recent call last):
+ ... ...
+ ... NameError: name 'y' is not defined
...
... But the captured globals will still be defined.
...
@@ -100,9 +100,3 @@
... """)
>>> 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
Modified: manuel/trunk/src/manuel/table-example.txt
===================================================================
--- manuel/trunk/src/manuel/table-example.txt 2009-06-19 20:56:53 UTC (rev 101154)
+++ manuel/trunk/src/manuel/table-example.txt 2009-06-19 21:55:17 UTC (rev 101155)
@@ -3,6 +3,8 @@
FIT Table Example
=================
+Here is an example of writing a relatively complex Manuel plug-in.
+
Occasionally when writing a doctest, you want a better way to express a test
than doctest by itself provides.
@@ -307,7 +309,7 @@
file named "my-table-tests.txt" we can create a file named tests.py and build a
TestSuite like so:
-.. this next chunk isn't actually executed by tests, so watch out
+.. ignore-next-block
.. code-block:: python
import unittest
Modified: manuel/trunk/src/manuel/testing.py
===================================================================
--- manuel/trunk/src/manuel/testing.py 2009-06-19 20:56:53 UTC (rev 101154)
+++ manuel/trunk/src/manuel/testing.py 2009-06-19 21:55:17 UTC (rev 101155)
@@ -8,8 +8,6 @@
class TestCase(unittest.TestCase):
- __test__ = False # tell nose not to treat this as a test case
-
# XXX this is broken, see the unittest.TestCase docstring
def __init__(self, m, document, setUp=None, tearDown=None, globs=None):
unittest.TestCase.__init__(self)
@@ -105,5 +103,3 @@
suite.addTest(TestCase(m, document, **kws))
return suite
-
-TestSuite.__test__ = False # tell nose not to treat this as a test case
Modified: manuel/trunk/src/manuel/tests.py
===================================================================
--- manuel/trunk/src/manuel/tests.py 2009-06-19 20:56:53 UTC (rev 101154)
+++ manuel/trunk/src/manuel/tests.py 2009-06-19 21:55:17 UTC (rev 101155)
@@ -2,6 +2,7 @@
import manuel
import manuel.codeblock
import manuel.doctest
+import manuel.ignore
import manuel.testing
import os.path
import re
@@ -30,23 +31,18 @@
suite = unittest.TestSuite()
tests = ['README.txt', 'footnote.txt', 'bugs.txt', 'codeblock.txt',
- 'isolation.txt', 'table-example.txt']
+ 'isolation.txt', 'table-example.txt', '../getting-started.txt',
+ 'ignore.txt']
tests = map(get_abs_path, tests)
- # run the tests with Manuel's doctest support
- m = manuel.doctest.Manuel(optionflags=optionflags, checker=checker)
- # add in the codeblock extension
+ m = manuel.ignore.Manuel()
+ m.extend(manuel.doctest.Manuel(optionflags=optionflags, checker=checker))
m.extend(manuel.codeblock.Manuel())
- # build the test suite
suite.addTest(manuel.testing.TestSuite(m, *tests))
return suite
-test_suite.__test__ = False # tell nose not to treat this as a test case
-def run_tests():
- unittest.TextTestRunner().run(test_suite())
-
if __name__ == '__main__':
- run_tests()
+ unittest.TextTestRunner().run(test_suite())
More information about the Checkins
mailing list