diff --git a/IPython/testing/iptest.py b/IPython/testing/iptest.py index 9e4f74b..2deefed 100644 --- a/IPython/testing/iptest.py +++ b/IPython/testing/iptest.py @@ -41,7 +41,6 @@ EXCLUDE = ['IPython/external/', 'IPython/Extensions/clearcmd', 'IPython/Extensions/PhysicalQIn', 'IPython/Extensions/scitedirector', - 'IPython/testing/plugin', ] #----------------------------------------------------------------------------- diff --git a/IPython/testing/plugin/dtexample.py b/IPython/testing/plugin/dtexample.py index 3a29b4a..453aac3 100644 --- a/IPython/testing/plugin/dtexample.py +++ b/IPython/testing/plugin/dtexample.py @@ -29,9 +29,6 @@ def ipfunc(): In [1]: import os - In [2]: cd / - / - In [3]: 2+3 Out[3]: 5 diff --git a/IPython/testing/plugin/ipdoctest.py b/IPython/testing/plugin/ipdoctest.py index d6c9996..64e6a2c 100644 --- a/IPython/testing/plugin/ipdoctest.py +++ b/IPython/testing/plugin/ipdoctest.py @@ -392,7 +392,6 @@ class DocTestCase(doctests.DocTestCase): self._dt_test.globs = _ip.IP.user_ns doctests.DocTestCase.setUp(self) - # A simple subclassing of the original with a different class name, so we can @@ -464,7 +463,11 @@ class IPDocTestParser(doctest.DocTestParser): """Convert input IPython source into valid Python.""" out = [] newline = out.append - for lnum,line in enumerate(source.splitlines()): + #print 'IPSRC:\n',source,'\n###' # dbg + # The input source must be first stripped of all bracketing whitespace + # and turned into lines, so it looks to the parser like regular user + # input + for lnum,line in enumerate(source.strip().splitlines()): newline(_ip.IP.prefilter(line,lnum>0)) newline('') # ensure a closing newline, needed by doctest #print "PYSRC:", '\n'.join(out) # dbg diff --git a/IPython/tests/test_iplib.py b/IPython/tests/test_iplib.py index ad9bb15..42fa1b6 100644 --- a/IPython/tests/test_iplib.py +++ b/IPython/tests/test_iplib.py @@ -3,6 +3,7 @@ import nose.tools as nt + def test_reset(): """reset must clear most namespaces.""" ip = _ip.IP diff --git a/docs/source/development/overview.txt b/docs/source/development/overview.txt index 1f0836a..a0dcd9b 100644 --- a/docs/source/development/overview.txt +++ b/docs/source/development/overview.txt @@ -283,6 +283,39 @@ installed with IPython:: This command runs Nose with the proper options and extensions. +A few tips for writing tests: + +* You can use IPython examples in your docstrings, including all IPython + prompts. Rather than repeating it all here, see the files + :file:`dtexample.py` and :file:`test_ipdoctest.py` in the + :mod:`IPython.testing.plugin` module for examples of how you can use plain + Python or IPython prompts, and what to do with examples whose output could be + partly or completely random. + +* Use the decorators shipped in the :mod:`IPython.testing` package to tag tests + that may be platform-specific or otherwise may have restrictions. + +* If a test isn't safe to run inside the main nose process (e.g. because it + loads a GUI toolkit), consider running it in a subprocess and capturing its + output for evaluation and test decision later. Here is an example of how to + do it, by relying on the builtin ``_ip`` object that contains the public + IPython api as defined in :mod:`IPython.ipapi`:: + + def test_obj_del(): + """Test that object's __del__ methods are called on exit.""" + test_dir = os.path.dirname(__file__) + del_file = os.path.join(test_dir,'obj_del.py') + out = _ip.IP.getoutput('ipython %s' % del_file) + nt.assert_equals(out,'object A deleted') + + +* In a file named ``test_X``, functions whose only test is their docstring (as + a doctest) and which have no test functionality of their own, should be + called *doctest_foo* instead of *test_foo*, otherwise they get double-counted + (the empty function call is counted as a test, which just inflates tests + numbers artificially). This restriction does not apply to functions in files + with other names, due to how Nose discovers tests. + .. _devel_config: Release checklist