From 0b100f181e9a5179d6469f60b51529a7c48fd76f 2008-07-17 07:17:14
From: Fernando Perez <Fernando.Perez@berkeley.edu>
Date: 2008-07-17 07:17:14
Subject: [PATCH] Checkpoint where tests are recognized.  Random tests not working yet.

---

diff --git a/IPython/testing/plugin/Makefile b/IPython/testing/plugin/Makefile
index 5c5d1cb..77392f5 100644
--- a/IPython/testing/plugin/Makefile
+++ b/IPython/testing/plugin/Makefile
@@ -4,8 +4,12 @@ PREFIX=~/tmp/local
 
 plugin: IPython_doctest_plugin.egg-info
 
+dtest: plugin dtexample.py
+	nosetests -vs --with-ipdoctest --doctest-tests --doctest-extension=txt \
+	dtexample.py
+
 test: plugin dtexample.py
-	nosetests -s --with-ipdoctest --doctest-tests --doctest-extension=txt \
+	nosetests -vs --with-ipdoctest --doctest-tests --doctest-extension=txt \
 	dtexample.py test*.txt
 
 deb: plugin dtexample.py
diff --git a/IPython/testing/plugin/dtexample.py b/IPython/testing/plugin/dtexample.py
index d4b6d01..0d69718 100644
--- a/IPython/testing/plugin/dtexample.py
+++ b/IPython/testing/plugin/dtexample.py
@@ -70,3 +70,38 @@ def ipfunc():
 
     return 'ipfunc'
 
+
+def ranfunc():
+    """A function with some random output.
+
+       >>> 1+3 #random
+       junk goes here...
+
+       >>> 1+3
+       4
+
+       >>> 1+2 #random
+       again,  anything goes
+    """
+    return 'ranfunc'
+
+
+def ranf2():
+    """A function whose examples are all all random
+
+    Examples:
+
+    #all-random
+
+       >>> 1+3 #random
+       junk goes here...
+
+       >>> 1+3
+       klasdfj;
+
+       >>> 1+2 #random
+       again,  anything goes
+
+    """
+    return 'ranf2'
+
diff --git a/IPython/testing/plugin/ipdoctest.py b/IPython/testing/plugin/ipdoctest.py
index cde2895..0d0ec4c 100644
--- a/IPython/testing/plugin/ipdoctest.py
+++ b/IPython/testing/plugin/ipdoctest.py
@@ -222,6 +222,20 @@ class DocTestCase(doctests.DocTestCase):
     for purposes of determining the test address, if it is provided.
     """
 
+    # Note: this method was taken from numpy's nosetester module.
+    
+    # Subclass nose.plugins.doctests.DocTestCase to work around a bug in 
+    # its constructor that blocks non-default arguments from being passed
+    # down into doctest.DocTestCase
+    ## def __init__(self, test, optionflags=0, setUp=None, tearDown=None,
+    ##              checker=None, obj=None, result_var='_'):
+    ##     self._result_var = result_var
+    ##     self._nose_obj = obj
+    ##     doctest.DocTestCase.__init__(self, test, 
+    ##                                  optionflags=optionflags,
+    ##                                  setUp=setUp, tearDown=tearDown, 
+    ##                                  checker=checker)
+
     # doctests loaded via find(obj) omit the module name
     # so we need to override id, __repr__ and shortDescription
     # bonus: this will squash a 2.3 vs 2.4 incompatiblity
@@ -235,6 +249,7 @@ class DocTestCase(doctests.DocTestCase):
         return name
 
 
+
 # A simple subclassing of the original with a different class name, so we can
 # distinguish and treat differently IPython examples from pure python ones.
 class IPExample(doctest.Example): pass
@@ -311,7 +326,7 @@ class IPDocTestParser(doctest.DocTestParser):
         used for error messages.
         """
 
-        #print 'Parse string:\n',string # dbg
+        print 'Parse string:\n',string # dbg
 
         string = string.expandtabs()
         # If all lines begin with the same indentation, then strip it.
@@ -376,6 +391,8 @@ class IPDocTestParser(doctest.DocTestParser):
         # Add any remaining post-example text to `output`.
         output.append(string[charno:])
 
+        #print 'OUT:',output  # dbg
+
         return output
 
     def _parse_example(self, m, name, lineno,ip2py=False):
@@ -501,6 +518,8 @@ class ExtensionDoctest(doctests.Doctest):
         return tests
 
     def loadTestsFromFile(self, filename):
+        print 'lTF',filename  # dbg
+
         if is_extension_module(filename):
             for t in self.loadTestsFromExtensionModule(filename):
                 yield t
@@ -510,7 +529,6 @@ class ExtensionDoctest(doctests.Doctest):
             pass
 
         if self.extension and anyp(filename.endswith, self.extension):
-            #print 'lTF',filename  # dbg
             name = os.path.basename(filename)
             dh = open(filename)
             try:
@@ -532,7 +550,7 @@ class ExtensionDoctest(doctests.Doctest):
         Modified version that accepts extension modules as valid containers for
         doctests.
         """
-        #print 'Filename:',filename  # dbg
+        print 'Filename:',filename  # dbg
 
         # temporarily hardcoded list, will move to driver later
         exclude = ['IPython/external/',
@@ -553,14 +571,9 @@ class ExtensionDoctest(doctests.Doctest):
         else:
             return doctests.Doctest.wantFile(self,filename)
 
-    # NOTE: the method below is a *copy* of the one in the nose doctests
-    # plugin, but we have to replicate it here in order to have it resolve the
-    # DocTestCase (last line) to our local copy, since the nose plugin doesn't
-    # provide a public hook for what TestCase class to use.  The alternative
-    # would be to monkeypatch doctest in the stdlib, but that's ugly and
-    # brittle, since a change in plugin load order can break it.  So for now,
-    # we just paste this in here, inelegant as this may be.
-
+    # NOTE: the method below is almost a copy of the original one in nose, with
+    # a  few modifications to control output checking.
+    
     def loadTestsFromModule(self, module):
         #print 'lTM',module  # dbg
 
@@ -581,6 +594,15 @@ class ExtensionDoctest(doctests.Doctest):
                 test.filename = module_file
             yield DocTestCase(test)
 
+            # always use whitespace and ellipsis options
+            optionflags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
+            #checker = DoctestOutputChecker()
+            checker = None
+            yield DocTestCase(test, 
+                              optionflags=optionflags,
+                              checker=checker)
+
+
 
 class IPythonDoctest(ExtensionDoctest):
     """Nose Plugin that supports doctests in extension modules.
@@ -594,5 +616,4 @@ class IPythonDoctest(ExtensionDoctest):
         self.doctest_tests = options.doctest_tests
         self.extension = tolist(options.doctestExtension)
         self.parser = IPDocTestParser()
-        #self.finder = DocTestFinder(parser=IPDocTestParser())
         self.finder = DocTestFinder(parser=self.parser)