##// END OF EJS Templates
Added diagnostics printout at the end of the test suite....
Fernando Perez -
Show More
@@ -1,121 +1,121 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Release data for the IPython project."""
2 """Release data for the IPython project."""
3
3
4 #*****************************************************************************
4 #*****************************************************************************
5 # Copyright (C) 2008-2009 The IPython Development Team
5 # Copyright (C) 2008-2009 The IPython Development Team
6 # Copyright (C) 2001-2008 Fernando Perez <fperez@colorado.edu>
6 # Copyright (C) 2001-2008 Fernando Perez <fperez@colorado.edu>
7 # Copyright (c) 2001 Janko Hauser <jhauser@zscout.de> and Nathaniel Gray
7 # Copyright (c) 2001 Janko Hauser <jhauser@zscout.de> and Nathaniel Gray
8 # <n8gray@caltech.edu>
8 # <n8gray@caltech.edu>
9 #
9 #
10 # Distributed under the terms of the BSD License. The full license is in
10 # Distributed under the terms of the BSD License. The full license is in
11 # the file COPYING, distributed as part of this software.
11 # the file COPYING, distributed as part of this software.
12 #*****************************************************************************
12 #*****************************************************************************
13
13
14 # Name of the package for release purposes. This is the name which labels
14 # Name of the package for release purposes. This is the name which labels
15 # the tarballs and RPMs made by distutils, so it's best to lowercase it.
15 # the tarballs and RPMs made by distutils, so it's best to lowercase it.
16 name = 'ipython'
16 name = 'ipython'
17
17
18 # For versions with substrings (like 0.6.16.svn), use an extra . to separate
18 # For versions with substrings (like 0.6.16.svn), use an extra . to separate
19 # the new substring. We have to avoid using either dashes or underscores,
19 # the new substring. We have to avoid using either dashes or underscores,
20 # because bdist_rpm does not accept dashes (an RPM) convention, and
20 # because bdist_rpm does not accept dashes (an RPM) convention, and
21 # bdist_deb does not accept underscores (a Debian convention).
21 # bdist_deb does not accept underscores (a Debian convention).
22
22
23 development = True # change this to False to do a release
23 development = True # change this to False to do a release
24 version_base = '0.11'
24 version_base = '0.11'
25 branch = 'ipython'
25 branch = 'ipython'
26 revision = '1340'
26 revision = '1346'
27
27
28 if development:
28 if development:
29 if branch == 'ipython':
29 if branch == 'ipython':
30 version = '%s.bzr.r%s' % (version_base, revision)
30 version = '%s.bzr.r%s' % (version_base, revision)
31 else:
31 else:
32 version = '%s.bzr.r%s.%s' % (version_base, revision, branch)
32 version = '%s.bzr.r%s.%s' % (version_base, revision, branch)
33 else:
33 else:
34 version = version_base
34 version = version_base
35
35
36
36
37 description = "An interactive computing environment for Python"
37 description = "An interactive computing environment for Python"
38
38
39 long_description = \
39 long_description = \
40 """
40 """
41 The goal of IPython is to create a comprehensive environment for
41 The goal of IPython is to create a comprehensive environment for
42 interactive and exploratory computing. To support this goal, IPython
42 interactive and exploratory computing. To support this goal, IPython
43 has two main components:
43 has two main components:
44
44
45 * An enhanced interactive Python shell.
45 * An enhanced interactive Python shell.
46
46
47 * An architecture for interactive parallel computing.
47 * An architecture for interactive parallel computing.
48
48
49 The enhanced interactive Python shell has the following main features:
49 The enhanced interactive Python shell has the following main features:
50
50
51 * Comprehensive object introspection.
51 * Comprehensive object introspection.
52
52
53 * Input history, persistent across sessions.
53 * Input history, persistent across sessions.
54
54
55 * Caching of output results during a session with automatically generated
55 * Caching of output results during a session with automatically generated
56 references.
56 references.
57
57
58 * Readline based name completion.
58 * Readline based name completion.
59
59
60 * Extensible system of 'magic' commands for controlling the environment and
60 * Extensible system of 'magic' commands for controlling the environment and
61 performing many tasks related either to IPython or the operating system.
61 performing many tasks related either to IPython or the operating system.
62
62
63 * Configuration system with easy switching between different setups (simpler
63 * Configuration system with easy switching between different setups (simpler
64 than changing $PYTHONSTARTUP environment variables every time).
64 than changing $PYTHONSTARTUP environment variables every time).
65
65
66 * Session logging and reloading.
66 * Session logging and reloading.
67
67
68 * Extensible syntax processing for special purpose situations.
68 * Extensible syntax processing for special purpose situations.
69
69
70 * Access to the system shell with user-extensible alias system.
70 * Access to the system shell with user-extensible alias system.
71
71
72 * Easily embeddable in other Python programs and wxPython GUIs.
72 * Easily embeddable in other Python programs and wxPython GUIs.
73
73
74 * Integrated access to the pdb debugger and the Python profiler.
74 * Integrated access to the pdb debugger and the Python profiler.
75
75
76 The parallel computing architecture has the following main features:
76 The parallel computing architecture has the following main features:
77
77
78 * Quickly parallelize Python code from an interactive Python/IPython session.
78 * Quickly parallelize Python code from an interactive Python/IPython session.
79
79
80 * A flexible and dynamic process model that be deployed on anything from
80 * A flexible and dynamic process model that be deployed on anything from
81 multicore workstations to supercomputers.
81 multicore workstations to supercomputers.
82
82
83 * An architecture that supports many different styles of parallelism, from
83 * An architecture that supports many different styles of parallelism, from
84 message passing to task farming.
84 message passing to task farming.
85
85
86 * Both blocking and fully asynchronous interfaces.
86 * Both blocking and fully asynchronous interfaces.
87
87
88 * High level APIs that enable many things to be parallelized in a few lines
88 * High level APIs that enable many things to be parallelized in a few lines
89 of code.
89 of code.
90
90
91 * Share live parallel jobs with other users securely.
91 * Share live parallel jobs with other users securely.
92
92
93 * Dynamically load balanced task farming system.
93 * Dynamically load balanced task farming system.
94
94
95 * Robust error handling in parallel code.
95 * Robust error handling in parallel code.
96
96
97 The latest development version is always available from IPython's `Launchpad
97 The latest development version is always available from IPython's `Launchpad
98 site <http://launchpad.net/ipython>`_.
98 site <http://launchpad.net/ipython>`_.
99 """
99 """
100
100
101 license = 'BSD'
101 license = 'BSD'
102
102
103 authors = {'Fernando' : ('Fernando Perez','fperez.net@gmail.com'),
103 authors = {'Fernando' : ('Fernando Perez','fperez.net@gmail.com'),
104 'Janko' : ('Janko Hauser','jhauser@zscout.de'),
104 'Janko' : ('Janko Hauser','jhauser@zscout.de'),
105 'Nathan' : ('Nathaniel Gray','n8gray@caltech.edu'),
105 'Nathan' : ('Nathaniel Gray','n8gray@caltech.edu'),
106 'Ville' : ('Ville Vainio','vivainio@gmail.com'),
106 'Ville' : ('Ville Vainio','vivainio@gmail.com'),
107 'Brian' : ('Brian E Granger', 'ellisonbg@gmail.com'),
107 'Brian' : ('Brian E Granger', 'ellisonbg@gmail.com'),
108 'Min' : ('Min Ragan-Kelley', 'benjaminrk@gmail.com')
108 'Min' : ('Min Ragan-Kelley', 'benjaminrk@gmail.com')
109 }
109 }
110
110
111 author = 'The IPython Development Team'
111 author = 'The IPython Development Team'
112
112
113 author_email = 'ipython-dev@scipy.org'
113 author_email = 'ipython-dev@scipy.org'
114
114
115 url = 'http://ipython.scipy.org'
115 url = 'http://ipython.scipy.org'
116
116
117 download_url = 'http://ipython.scipy.org/dist'
117 download_url = 'http://ipython.scipy.org/dist'
118
118
119 platforms = ['Linux','Mac OSX','Windows XP/2000/NT','Windows 95/98/ME']
119 platforms = ['Linux','Mac OSX','Windows XP/2000/NT','Windows 95/98/ME']
120
120
121 keywords = ['Interactive','Interpreter','Shell','Parallel','Distributed']
121 keywords = ['Interactive','Interpreter','Shell','Parallel','Distributed']
@@ -1,450 +1,488 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """IPython Test Suite Runner.
2 """IPython Test Suite Runner.
3
3
4 This module provides a main entry point to a user script to test IPython
4 This module provides a main entry point to a user script to test IPython
5 itself from the command line. There are two ways of running this script:
5 itself from the command line. There are two ways of running this script:
6
6
7 1. With the syntax `iptest all`. This runs our entire test suite by
7 1. With the syntax `iptest all`. This runs our entire test suite by
8 calling this script (with different arguments) or trial recursively. This
8 calling this script (with different arguments) or trial recursively. This
9 causes modules and package to be tested in different processes, using nose
9 causes modules and package to be tested in different processes, using nose
10 or trial where appropriate.
10 or trial where appropriate.
11 2. With the regular nose syntax, like `iptest -vvs IPython`. In this form
11 2. With the regular nose syntax, like `iptest -vvs IPython`. In this form
12 the script simply calls nose, but with special command line flags and
12 the script simply calls nose, but with special command line flags and
13 plugins loaded.
13 plugins loaded.
14
14
15 For now, this script requires that both nose and twisted are installed. This
15 For now, this script requires that both nose and twisted are installed. This
16 will change in the future.
16 will change in the future.
17 """
17 """
18
18
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20 # Module imports
20 # Module imports
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22
22
23 # Stdlib
23 # Stdlib
24 import os
24 import os
25 import os.path as path
25 import os.path as path
26 import platform
26 import signal
27 import signal
27 import sys
28 import sys
28 import subprocess
29 import subprocess
29 import tempfile
30 import tempfile
30 import time
31 import time
31 import warnings
32 import warnings
32
33
33
34
34 # Ugly, but necessary hack to ensure the test suite finds our version of
35 # Ugly, but necessary hack to ensure the test suite finds our version of
35 # IPython and not a possibly different one that may exist system-wide.
36 # IPython and not a possibly different one that may exist system-wide.
36 # Note that this must be done here, so the imports that come next work
37 # Note that this must be done here, so the imports that come next work
37 # correctly even if IPython isn't installed yet.
38 # correctly even if IPython isn't installed yet.
38 p = os.path
39 p = os.path
39 ippath = p.abspath(p.join(p.dirname(__file__),'..','..'))
40 ippath = p.abspath(p.join(p.dirname(__file__),'..','..'))
40 sys.path.insert(0, ippath)
41 sys.path.insert(0, ippath)
41
42
42 # Note: monkeypatch!
43 # Note: monkeypatch!
43 # We need to monkeypatch a small problem in nose itself first, before importing
44 # We need to monkeypatch a small problem in nose itself first, before importing
44 # it for actual use. This should get into nose upstream, but its release cycle
45 # it for actual use. This should get into nose upstream, but its release cycle
45 # is slow and we need it for our parametric tests to work correctly.
46 # is slow and we need it for our parametric tests to work correctly.
46 from IPython.testing import nosepatch
47 from IPython.testing import nosepatch
47 # Now, proceed to import nose itself
48 # Now, proceed to import nose itself
48 import nose.plugins.builtin
49 import nose.plugins.builtin
49 from nose.core import TestProgram
50 from nose.core import TestProgram
50
51
51 # Our own imports
52 # Our own imports
53 from IPython.core import release
52 from IPython.utils import genutils
54 from IPython.utils import genutils
53 from IPython.utils.platutils import find_cmd, FindCmdError
55 from IPython.utils.platutils import find_cmd, FindCmdError
54 from IPython.testing import globalipapp
56 from IPython.testing import globalipapp
55 from IPython.testing import tools
57 from IPython.testing import tools
56 from IPython.testing.plugin.ipdoctest import IPythonDoctest
58 from IPython.testing.plugin.ipdoctest import IPythonDoctest
57
59
58 pjoin = path.join
60 pjoin = path.join
59
61
60
62
61 #-----------------------------------------------------------------------------
63 #-----------------------------------------------------------------------------
62 # Globals
64 # Globals
63 #-----------------------------------------------------------------------------
65 #-----------------------------------------------------------------------------
64
66
65 # By default, we assume IPython has been installed. But if the test suite is
67 # By default, we assume IPython has been installed. But if the test suite is
66 # being run from a source tree that has NOT been installed yet, this flag can
68 # being run from a source tree that has NOT been installed yet, this flag can
67 # be set to False by the entry point scripts, to let us know that we must call
69 # be set to False by the entry point scripts, to let us know that we must call
68 # the source tree versions of the scripts which manipulate sys.path instead of
70 # the source tree versions of the scripts which manipulate sys.path instead of
69 # assuming that things exist system-wide.
71 # assuming that things exist system-wide.
70 INSTALLED = True
72 INSTALLED = True
71
73
72 #-----------------------------------------------------------------------------
74 #-----------------------------------------------------------------------------
73 # Warnings control
75 # Warnings control
74 #-----------------------------------------------------------------------------
76 #-----------------------------------------------------------------------------
75 # Twisted generates annoying warnings with Python 2.6, as will do other code
77 # Twisted generates annoying warnings with Python 2.6, as will do other code
76 # that imports 'sets' as of today
78 # that imports 'sets' as of today
77 warnings.filterwarnings('ignore', 'the sets module is deprecated',
79 warnings.filterwarnings('ignore', 'the sets module is deprecated',
78 DeprecationWarning )
80 DeprecationWarning )
79
81
80 # This one also comes from Twisted
82 # This one also comes from Twisted
81 warnings.filterwarnings('ignore', 'the sha module is deprecated',
83 warnings.filterwarnings('ignore', 'the sha module is deprecated',
82 DeprecationWarning)
84 DeprecationWarning)
83
85
84 # Wx on Fedora11 spits these out
86 # Wx on Fedora11 spits these out
85 warnings.filterwarnings('ignore', 'wxPython/wxWidgets release number mismatch',
87 warnings.filterwarnings('ignore', 'wxPython/wxWidgets release number mismatch',
86 UserWarning)
88 UserWarning)
87
89
88 #-----------------------------------------------------------------------------
90 #-----------------------------------------------------------------------------
89 # Logic for skipping doctests
91 # Logic for skipping doctests
90 #-----------------------------------------------------------------------------
92 #-----------------------------------------------------------------------------
91
93
92 def test_for(mod):
94 def test_for(mod):
93 """Test to see if mod is importable."""
95 """Test to see if mod is importable."""
94 try:
96 try:
95 __import__(mod)
97 __import__(mod)
96 except (ImportError, RuntimeError):
98 except (ImportError, RuntimeError):
97 # GTK reports Runtime error if it can't be initialized even if it's
99 # GTK reports Runtime error if it can't be initialized even if it's
98 # importable.
100 # importable.
99 return False
101 return False
100 else:
102 else:
101 return True
103 return True
102
104
103 have_curses = test_for('_curses')
105 # Global dict where we can store information on what we have and what we don't
104 have_wx = test_for('wx')
106 # have available at test run time
105 have_wx_aui = test_for('wx.aui')
107 have = {}
106 have_zi = test_for('zope.interface')
108
107 have_twisted = test_for('twisted')
109 have['curses'] = test_for('_curses')
108 have_foolscap = test_for('foolscap')
110 have['wx'] = test_for('wx')
109 have_objc = test_for('objc')
111 have['wx.aui'] = test_for('wx.aui')
110 have_pexpect = test_for('pexpect')
112 have['zope.interface'] = test_for('zope.interface')
111 have_gtk = test_for('gtk')
113 have['twisted'] = test_for('twisted')
112 have_gobject = test_for('gobject')
114 have['foolscap'] = test_for('foolscap')
115 have['objc'] = test_for('objc')
116 have['pexpect'] = test_for('pexpect')
117 have['gtk'] = test_for('gtk')
118 have['gobject'] = test_for('gobject')
113
119
114 #-----------------------------------------------------------------------------
120 #-----------------------------------------------------------------------------
115 # Functions and classes
121 # Functions and classes
116 #-----------------------------------------------------------------------------
122 #-----------------------------------------------------------------------------
117
123
124 def report():
125 """Return a string with a summary report of test-related variables."""
126
127 out = [ genutils.sys_info() ]
128
129 out.append('\nRunning from an installed IPython: %s\n' % INSTALLED)
130
131 avail = []
132 not_avail = []
133
134 for k, is_avail in have.items():
135 if is_avail:
136 avail.append(k)
137 else:
138 not_avail.append(k)
139
140 if avail:
141 out.append('\nTools and libraries available at test time:\n')
142 avail.sort()
143 out.append(' ' + ' '.join(avail)+'\n')
144
145 if not_avail:
146 out.append('\nTools and libraries NOT available at test time:\n')
147 not_avail.sort()
148 out.append(' ' + ' '.join(not_avail)+'\n')
149
150 return ''.join(out)
151
152
118 def make_exclude():
153 def make_exclude():
119 """Make patterns of modules and packages to exclude from testing.
154 """Make patterns of modules and packages to exclude from testing.
120
155
121 For the IPythonDoctest plugin, we need to exclude certain patterns that
156 For the IPythonDoctest plugin, we need to exclude certain patterns that
122 cause testing problems. We should strive to minimize the number of
157 cause testing problems. We should strive to minimize the number of
123 skipped modules, since this means untested code. As the testing
158 skipped modules, since this means untested code. As the testing
124 machinery solidifies, this list should eventually become empty.
159 machinery solidifies, this list should eventually become empty.
125 These modules and packages will NOT get scanned by nose at all for tests.
160 These modules and packages will NOT get scanned by nose at all for tests.
126 """
161 """
127 # Simple utility to make IPython paths more readably, we need a lot of
162 # Simple utility to make IPython paths more readably, we need a lot of
128 # these below
163 # these below
129 ipjoin = lambda *paths: pjoin('IPython', *paths)
164 ipjoin = lambda *paths: pjoin('IPython', *paths)
130
165
131 exclusions = [ipjoin('external'),
166 exclusions = [ipjoin('external'),
132 ipjoin('frontend', 'process', 'winprocess.py'),
167 ipjoin('frontend', 'process', 'winprocess.py'),
133 # Deprecated old Shell and iplib modules, skip to avoid
168 # Deprecated old Shell and iplib modules, skip to avoid
134 # warnings
169 # warnings
135 ipjoin('Shell'),
170 ipjoin('Shell'),
136 ipjoin('iplib'),
171 ipjoin('iplib'),
137 pjoin('IPython_doctest_plugin'),
172 pjoin('IPython_doctest_plugin'),
138 ipjoin('quarantine'),
173 ipjoin('quarantine'),
139 ipjoin('deathrow'),
174 ipjoin('deathrow'),
140 ipjoin('testing', 'attic'),
175 ipjoin('testing', 'attic'),
141 # This guy is probably attic material
176 # This guy is probably attic material
142 ipjoin('testing', 'mkdoctests'),
177 ipjoin('testing', 'mkdoctests'),
143 # Testing inputhook will need a lot of thought, to figure out
178 # Testing inputhook will need a lot of thought, to figure out
144 # how to have tests that don't lock up with the gui event
179 # how to have tests that don't lock up with the gui event
145 # loops in the picture
180 # loops in the picture
146 ipjoin('lib', 'inputhook'),
181 ipjoin('lib', 'inputhook'),
147 # Config files aren't really importable stand-alone
182 # Config files aren't really importable stand-alone
148 ipjoin('config', 'default'),
183 ipjoin('config', 'default'),
149 ipjoin('config', 'profile'),
184 ipjoin('config', 'profile'),
150 ]
185 ]
151
186
152 if not have_wx:
187 if not have['wx']:
153 exclusions.append(ipjoin('gui'))
188 exclusions.append(ipjoin('gui'))
154 exclusions.append(ipjoin('frontend', 'wx'))
189 exclusions.append(ipjoin('frontend', 'wx'))
155 exclusions.append(ipjoin('lib', 'inputhookwx'))
190 exclusions.append(ipjoin('lib', 'inputhookwx'))
156
191
157 if not have_gtk or not have_gobject:
192 if not have['gtk'] or not have['gobject']:
158 exclusions.append(ipjoin('lib', 'inputhookgtk'))
193 exclusions.append(ipjoin('lib', 'inputhookgtk'))
159
194
160 if not have_wx_aui:
195 if not have['wx.aui']:
161 exclusions.append(ipjoin('gui', 'wx', 'wxIPython'))
196 exclusions.append(ipjoin('gui', 'wx', 'wxIPython'))
162
197
163 if not have_objc:
198 if not have['objc']:
164 exclusions.append(ipjoin('frontend', 'cocoa'))
199 exclusions.append(ipjoin('frontend', 'cocoa'))
165
200
166 if not sys.platform == 'win32':
201 if not sys.platform == 'win32':
167 exclusions.append(ipjoin('utils', 'platutils_win32'))
202 exclusions.append(ipjoin('utils', 'platutils_win32'))
168
203
169 # These have to be skipped on win32 because the use echo, rm, cd, etc.
204 # These have to be skipped on win32 because the use echo, rm, cd, etc.
170 # See ticket https://bugs.launchpad.net/bugs/366982
205 # See ticket https://bugs.launchpad.net/bugs/366982
171 if sys.platform == 'win32':
206 if sys.platform == 'win32':
172 exclusions.append(ipjoin('testing', 'plugin', 'test_exampleip'))
207 exclusions.append(ipjoin('testing', 'plugin', 'test_exampleip'))
173 exclusions.append(ipjoin('testing', 'plugin', 'dtexample'))
208 exclusions.append(ipjoin('testing', 'plugin', 'dtexample'))
174
209
175 if not os.name == 'posix':
210 if not os.name == 'posix':
176 exclusions.append(ipjoin('utils', 'platutils_posix'))
211 exclusions.append(ipjoin('utils', 'platutils_posix'))
177
212
178 if not have_pexpect:
213 if not have['pexpect']:
179 exclusions.extend([ipjoin('scripts', 'irunner'),
214 exclusions.extend([ipjoin('scripts', 'irunner'),
180 ipjoin('lib', 'irunner')])
215 ipjoin('lib', 'irunner')])
181
216
182 # This is scary. We still have things in frontend and testing that
217 # This is scary. We still have things in frontend and testing that
183 # are being tested by nose that use twisted. We need to rethink
218 # are being tested by nose that use twisted. We need to rethink
184 # how we are isolating dependencies in testing.
219 # how we are isolating dependencies in testing.
185 if not (have_twisted and have_zi and have_foolscap):
220 if not (have['twisted'] and have['zope.interface'] and have['foolscap']):
186 exclusions.extend(
221 exclusions.extend(
187 [ipjoin('frontend', 'asyncfrontendbase'),
222 [ipjoin('frontend', 'asyncfrontendbase'),
188 ipjoin('frontend', 'prefilterfrontend'),
223 ipjoin('frontend', 'prefilterfrontend'),
189 ipjoin('frontend', 'frontendbase'),
224 ipjoin('frontend', 'frontendbase'),
190 ipjoin('frontend', 'linefrontendbase'),
225 ipjoin('frontend', 'linefrontendbase'),
191 ipjoin('frontend', 'tests', 'test_linefrontend'),
226 ipjoin('frontend', 'tests', 'test_linefrontend'),
192 ipjoin('frontend', 'tests', 'test_frontendbase'),
227 ipjoin('frontend', 'tests', 'test_frontendbase'),
193 ipjoin('frontend', 'tests', 'test_prefilterfrontend'),
228 ipjoin('frontend', 'tests', 'test_prefilterfrontend'),
194 ipjoin('frontend', 'tests', 'test_asyncfrontendbase'),
229 ipjoin('frontend', 'tests', 'test_asyncfrontendbase'),
195 ipjoin('testing', 'parametric'),
230 ipjoin('testing', 'parametric'),
196 ipjoin('testing', 'util'),
231 ipjoin('testing', 'util'),
197 ipjoin('testing', 'tests', 'test_decorators_trial'),
232 ipjoin('testing', 'tests', 'test_decorators_trial'),
198 ] )
233 ] )
199
234
200 # This is needed for the reg-exp to match on win32 in the ipdoctest plugin.
235 # This is needed for the reg-exp to match on win32 in the ipdoctest plugin.
201 if sys.platform == 'win32':
236 if sys.platform == 'win32':
202 exclusions = [s.replace('\\','\\\\') for s in exclusions]
237 exclusions = [s.replace('\\','\\\\') for s in exclusions]
203
238
204 return exclusions
239 return exclusions
205
240
206
241
207 class IPTester(object):
242 class IPTester(object):
208 """Call that calls iptest or trial in a subprocess.
243 """Call that calls iptest or trial in a subprocess.
209 """
244 """
210 #: string, name of test runner that will be called
245 #: string, name of test runner that will be called
211 runner = None
246 runner = None
212 #: list, parameters for test runner
247 #: list, parameters for test runner
213 params = None
248 params = None
214 #: list, arguments of system call to be made to call test runner
249 #: list, arguments of system call to be made to call test runner
215 call_args = None
250 call_args = None
216 #: list, process ids of subprocesses we start (for cleanup)
251 #: list, process ids of subprocesses we start (for cleanup)
217 pids = None
252 pids = None
218
253
219 def __init__(self, runner='iptest', params=None):
254 def __init__(self, runner='iptest', params=None):
220 """Create new test runner."""
255 """Create new test runner."""
221 p = os.path
256 p = os.path
222 if runner == 'iptest':
257 if runner == 'iptest':
223 if INSTALLED:
258 if INSTALLED:
224 self.runner = tools.cmd2argv(
259 self.runner = tools.cmd2argv(
225 p.abspath(find_cmd('iptest'))) + sys.argv[1:]
260 p.abspath(find_cmd('iptest'))) + sys.argv[1:]
226 else:
261 else:
227 # Find our own 'iptest' script OS-level entry point. Don't
262 # Find our own 'iptest' script OS-level entry point. Don't
228 # look system-wide, so we are sure we pick up *this one*. And
263 # look system-wide, so we are sure we pick up *this one*. And
229 # pass through to subprocess call our own sys.argv
264 # pass through to subprocess call our own sys.argv
230 ippath = p.abspath(p.join(p.dirname(__file__),'..','..'))
265 ippath = p.abspath(p.join(p.dirname(__file__),'..','..'))
231 script = p.join(ippath, 'iptest.py')
266 script = p.join(ippath, 'iptest.py')
232 self.runner = tools.cmd2argv(script) + sys.argv[1:]
267 self.runner = tools.cmd2argv(script) + sys.argv[1:]
233
268
234 else:
269 else:
235 # For trial, it needs to be installed system-wide
270 # For trial, it needs to be installed system-wide
236 self.runner = tools.cmd2argv(p.abspath(find_cmd('trial')))
271 self.runner = tools.cmd2argv(p.abspath(find_cmd('trial')))
237 if params is None:
272 if params is None:
238 params = []
273 params = []
239 if isinstance(params, str):
274 if isinstance(params, str):
240 params = [params]
275 params = [params]
241 self.params = params
276 self.params = params
242
277
243 # Assemble call
278 # Assemble call
244 self.call_args = self.runner+self.params
279 self.call_args = self.runner+self.params
245
280
246 # Store pids of anything we start to clean up on deletion, if possible
281 # Store pids of anything we start to clean up on deletion, if possible
247 # (on posix only, since win32 has no os.kill)
282 # (on posix only, since win32 has no os.kill)
248 self.pids = []
283 self.pids = []
249
284
250 if sys.platform == 'win32':
285 if sys.platform == 'win32':
251 def _run_cmd(self):
286 def _run_cmd(self):
252 # On Windows, use os.system instead of subprocess.call, because I
287 # On Windows, use os.system instead of subprocess.call, because I
253 # was having problems with subprocess and I just don't know enough
288 # was having problems with subprocess and I just don't know enough
254 # about win32 to debug this reliably. Os.system may be the 'old
289 # about win32 to debug this reliably. Os.system may be the 'old
255 # fashioned' way to do it, but it works just fine. If someone
290 # fashioned' way to do it, but it works just fine. If someone
256 # later can clean this up that's fine, as long as the tests run
291 # later can clean this up that's fine, as long as the tests run
257 # reliably in win32.
292 # reliably in win32.
258 return os.system(' '.join(self.call_args))
293 return os.system(' '.join(self.call_args))
259 else:
294 else:
260 def _run_cmd(self):
295 def _run_cmd(self):
261 #print >> sys.stderr, '*** CMD:', ' '.join(self.call_args) # dbg
296 #print >> sys.stderr, '*** CMD:', ' '.join(self.call_args) # dbg
262 subp = subprocess.Popen(self.call_args)
297 subp = subprocess.Popen(self.call_args)
263 self.pids.append(subp.pid)
298 self.pids.append(subp.pid)
264 # If this fails, the pid will be left in self.pids and cleaned up
299 # If this fails, the pid will be left in self.pids and cleaned up
265 # later, but if the wait call succeeds, then we can clear the
300 # later, but if the wait call succeeds, then we can clear the
266 # stored pid.
301 # stored pid.
267 retcode = subp.wait()
302 retcode = subp.wait()
268 self.pids.pop()
303 self.pids.pop()
269 return retcode
304 return retcode
270
305
271 def run(self):
306 def run(self):
272 """Run the stored commands"""
307 """Run the stored commands"""
273 try:
308 try:
274 return self._run_cmd()
309 return self._run_cmd()
275 except:
310 except:
276 import traceback
311 import traceback
277 traceback.print_exc()
312 traceback.print_exc()
278 return 1 # signal failure
313 return 1 # signal failure
279
314
280 def __del__(self):
315 def __del__(self):
281 """Cleanup on exit by killing any leftover processes."""
316 """Cleanup on exit by killing any leftover processes."""
282
317
283 if not hasattr(os, 'kill'):
318 if not hasattr(os, 'kill'):
284 return
319 return
285
320
286 for pid in self.pids:
321 for pid in self.pids:
287 try:
322 try:
288 print 'Cleaning stale PID:', pid
323 print 'Cleaning stale PID:', pid
289 os.kill(pid, signal.SIGKILL)
324 os.kill(pid, signal.SIGKILL)
290 except OSError:
325 except OSError:
291 # This is just a best effort, if we fail or the process was
326 # This is just a best effort, if we fail or the process was
292 # really gone, ignore it.
327 # really gone, ignore it.
293 pass
328 pass
294
329
295
330
296 def make_runners():
331 def make_runners():
297 """Define the top-level packages that need to be tested.
332 """Define the top-level packages that need to be tested.
298 """
333 """
299
334
300 # Packages to be tested via nose, that only depend on the stdlib
335 # Packages to be tested via nose, that only depend on the stdlib
301 nose_pkg_names = ['config', 'core', 'extensions', 'frontend', 'lib',
336 nose_pkg_names = ['config', 'core', 'extensions', 'frontend', 'lib',
302 'scripts', 'testing', 'utils' ]
337 'scripts', 'testing', 'utils' ]
303 # The machinery in kernel needs twisted for real testing
338 # The machinery in kernel needs twisted for real testing
304 trial_pkg_names = []
339 trial_pkg_names = []
305
340
306 if have_wx:
341 if have['wx']:
307 nose_pkg_names.append('gui')
342 nose_pkg_names.append('gui')
308
343
309 # And add twisted ones if conditions are met
344 # And add twisted ones if conditions are met
310 if have_zi and have_twisted and have_foolscap:
345 if have['zope.interface'] and have['twisted'] and have['foolscap']:
311 # Note that we list the kernel here, though the bulk of it is
346 # Note that we list the kernel here, though the bulk of it is
312 # twisted-based, because nose picks up doctests that twisted doesn't.
347 # twisted-based, because nose picks up doctests that twisted doesn't.
313 nose_pkg_names.append('kernel')
348 nose_pkg_names.append('kernel')
314 trial_pkg_names.append('kernel')
349 trial_pkg_names.append('kernel')
315
350
316 # For debugging this code, only load quick stuff
351 # For debugging this code, only load quick stuff
317 #nose_pkg_names = ['core', 'extensions'] # dbg
352 #nose_pkg_names = ['core', 'extensions'] # dbg
318 #trial_pkg_names = [] # dbg
353 #trial_pkg_names = [] # dbg
319
354
320 # Make fully qualified package names prepending 'IPython.' to our name lists
355 # Make fully qualified package names prepending 'IPython.' to our name lists
321 nose_packages = ['IPython.%s' % m for m in nose_pkg_names ]
356 nose_packages = ['IPython.%s' % m for m in nose_pkg_names ]
322 trial_packages = ['IPython.%s' % m for m in trial_pkg_names ]
357 trial_packages = ['IPython.%s' % m for m in trial_pkg_names ]
323
358
324 # Make runners
359 # Make runners
325 runners = [ (v, IPTester('iptest', params=v)) for v in nose_packages ]
360 runners = [ (v, IPTester('iptest', params=v)) for v in nose_packages ]
326 runners.extend([ (v, IPTester('trial', params=v)) for v in trial_packages ])
361 runners.extend([ (v, IPTester('trial', params=v)) for v in trial_packages ])
327
362
328 return runners
363 return runners
329
364
330
365
331 def run_iptest():
366 def run_iptest():
332 """Run the IPython test suite using nose.
367 """Run the IPython test suite using nose.
333
368
334 This function is called when this script is **not** called with the form
369 This function is called when this script is **not** called with the form
335 `iptest all`. It simply calls nose with appropriate command line flags
370 `iptest all`. It simply calls nose with appropriate command line flags
336 and accepts all of the standard nose arguments.
371 and accepts all of the standard nose arguments.
337 """
372 """
338
373
339 warnings.filterwarnings('ignore',
374 warnings.filterwarnings('ignore',
340 'This will be removed soon. Use IPython.testing.util instead')
375 'This will be removed soon. Use IPython.testing.util instead')
341
376
342 argv = sys.argv + [ '--detailed-errors', # extra info in tracebacks
377 argv = sys.argv + [ '--detailed-errors', # extra info in tracebacks
343
378
344 # Loading ipdoctest causes problems with Twisted, but
379 # Loading ipdoctest causes problems with Twisted, but
345 # our test suite runner now separates things and runs
380 # our test suite runner now separates things and runs
346 # all Twisted tests with trial.
381 # all Twisted tests with trial.
347 '--with-ipdoctest',
382 '--with-ipdoctest',
348 '--ipdoctest-tests','--ipdoctest-extension=txt',
383 '--ipdoctest-tests','--ipdoctest-extension=txt',
349
384
350 # We add --exe because of setuptools' imbecility (it
385 # We add --exe because of setuptools' imbecility (it
351 # blindly does chmod +x on ALL files). Nose does the
386 # blindly does chmod +x on ALL files). Nose does the
352 # right thing and it tries to avoid executables,
387 # right thing and it tries to avoid executables,
353 # setuptools unfortunately forces our hand here. This
388 # setuptools unfortunately forces our hand here. This
354 # has been discussed on the distutils list and the
389 # has been discussed on the distutils list and the
355 # setuptools devs refuse to fix this problem!
390 # setuptools devs refuse to fix this problem!
356 '--exe',
391 '--exe',
357 ]
392 ]
358
393
359 if nose.__version__ >= '0.11':
394 if nose.__version__ >= '0.11':
360 # I don't fully understand why we need this one, but depending on what
395 # I don't fully understand why we need this one, but depending on what
361 # directory the test suite is run from, if we don't give it, 0 tests
396 # directory the test suite is run from, if we don't give it, 0 tests
362 # get run. Specifically, if the test suite is run from the source dir
397 # get run. Specifically, if the test suite is run from the source dir
363 # with an argument (like 'iptest.py IPython.core', 0 tests are run,
398 # with an argument (like 'iptest.py IPython.core', 0 tests are run,
364 # even if the same call done in this directory works fine). It appears
399 # even if the same call done in this directory works fine). It appears
365 # that if the requested package is in the current dir, nose bails early
400 # that if the requested package is in the current dir, nose bails early
366 # by default. Since it's otherwise harmless, leave it in by default
401 # by default. Since it's otherwise harmless, leave it in by default
367 # for nose >= 0.11, though unfortunately nose 0.10 doesn't support it.
402 # for nose >= 0.11, though unfortunately nose 0.10 doesn't support it.
368 argv.append('--traverse-namespace')
403 argv.append('--traverse-namespace')
369
404
370 # Construct list of plugins, omitting the existing doctest plugin, which
405 # Construct list of plugins, omitting the existing doctest plugin, which
371 # ours replaces (and extends).
406 # ours replaces (and extends).
372 plugins = [IPythonDoctest(make_exclude())]
407 plugins = [IPythonDoctest(make_exclude())]
373 for p in nose.plugins.builtin.plugins:
408 for p in nose.plugins.builtin.plugins:
374 plug = p()
409 plug = p()
375 if plug.name == 'doctest':
410 if plug.name == 'doctest':
376 continue
411 continue
377 plugins.append(plug)
412 plugins.append(plug)
378
413
379 # We need a global ipython running in this process
414 # We need a global ipython running in this process
380 globalipapp.start_ipython()
415 globalipapp.start_ipython()
381 # Now nose can run
416 # Now nose can run
382 TestProgram(argv=argv, plugins=plugins)
417 TestProgram(argv=argv, plugins=plugins)
383
418
384
419
385 def run_iptestall():
420 def run_iptestall():
386 """Run the entire IPython test suite by calling nose and trial.
421 """Run the entire IPython test suite by calling nose and trial.
387
422
388 This function constructs :class:`IPTester` instances for all IPython
423 This function constructs :class:`IPTester` instances for all IPython
389 modules and package and then runs each of them. This causes the modules
424 modules and package and then runs each of them. This causes the modules
390 and packages of IPython to be tested each in their own subprocess using
425 and packages of IPython to be tested each in their own subprocess using
391 nose or twisted.trial appropriately.
426 nose or twisted.trial appropriately.
392 """
427 """
393
428
394 runners = make_runners()
429 runners = make_runners()
395
430
396 # Run the test runners in a temporary dir so we can nuke it when finished
431 # Run the test runners in a temporary dir so we can nuke it when finished
397 # to clean up any junk files left over by accident. This also makes it
432 # to clean up any junk files left over by accident. This also makes it
398 # robust against being run in non-writeable directories by mistake, as the
433 # robust against being run in non-writeable directories by mistake, as the
399 # temp dir will always be user-writeable.
434 # temp dir will always be user-writeable.
400 curdir = os.getcwd()
435 curdir = os.getcwd()
401 testdir = tempfile.gettempdir()
436 testdir = tempfile.gettempdir()
402 os.chdir(testdir)
437 os.chdir(testdir)
403
438
404 # Run all test runners, tracking execution time
439 # Run all test runners, tracking execution time
405 failed = []
440 failed = []
406 t_start = time.time()
441 t_start = time.time()
407 try:
442 try:
408 for (name, runner) in runners:
443 for (name, runner) in runners:
409 print '*'*70
444 print '*'*70
410 print 'IPython test group:',name
445 print 'IPython test group:',name
411 res = runner.run()
446 res = runner.run()
412 if res:
447 if res:
413 failed.append( (name, runner) )
448 failed.append( (name, runner) )
414 finally:
449 finally:
415 os.chdir(curdir)
450 os.chdir(curdir)
416 t_end = time.time()
451 t_end = time.time()
417 t_tests = t_end - t_start
452 t_tests = t_end - t_start
418 nrunners = len(runners)
453 nrunners = len(runners)
419 nfail = len(failed)
454 nfail = len(failed)
420 # summarize results
455 # summarize results
421 print
456 print
422 print '*'*70
457 print '*'*70
458 print 'Test suite completed for system with the following information:'
459 print report()
423 print 'Ran %s test groups in %.3fs' % (nrunners, t_tests)
460 print 'Ran %s test groups in %.3fs' % (nrunners, t_tests)
424 print
461 print
462 print 'Status:'
425 if not failed:
463 if not failed:
426 print 'OK'
464 print 'OK'
427 else:
465 else:
428 # If anything went wrong, point out what command to rerun manually to
466 # If anything went wrong, point out what command to rerun manually to
429 # see the actual errors and individual summary
467 # see the actual errors and individual summary
430 print 'ERROR - %s out of %s test groups failed.' % (nfail, nrunners)
468 print 'ERROR - %s out of %s test groups failed.' % (nfail, nrunners)
431 for name, failed_runner in failed:
469 for name, failed_runner in failed:
432 print '-'*40
470 print '-'*40
433 print 'Runner failed:',name
471 print 'Runner failed:',name
434 print 'You may wish to rerun this one individually, with:'
472 print 'You may wish to rerun this one individually, with:'
435 print ' '.join(failed_runner.call_args)
473 print ' '.join(failed_runner.call_args)
436 print
474 print
437
475
438
476
439 def main():
477 def main():
440 for arg in sys.argv[1:]:
478 for arg in sys.argv[1:]:
441 if arg.startswith('IPython'):
479 if arg.startswith('IPython'):
442 # This is in-process
480 # This is in-process
443 run_iptest()
481 run_iptest()
444 else:
482 else:
445 # This starts subprocesses
483 # This starts subprocesses
446 run_iptestall()
484 run_iptestall()
447
485
448
486
449 if __name__ == '__main__':
487 if __name__ == '__main__':
450 main()
488 main()
@@ -1,372 +1,388 b''
1 .. _testing:
1 .. _testing:
2
2
3 ==========================================
3 ==========================================
4 Testing IPython for users and developers
4 Testing IPython for users and developers
5 ==========================================
5 ==========================================
6
6
7 Overview
7 Overview
8 ========
8 ========
9
9
10 It is extremely important that all code contributed to IPython has tests.
10 It is extremely important that all code contributed to IPython has tests.
11 Tests should be written as unittests, doctests or other entities that the
11 Tests should be written as unittests, doctests or other entities that the
12 IPython test system can detect. See below for more details on this.
12 IPython test system can detect. See below for more details on this.
13
13
14 Each subpackage in IPython should have its own :file:`tests` directory that
14 Each subpackage in IPython should have its own :file:`tests` directory that
15 contains all of the tests for that subpackage. All of the files in the
15 contains all of the tests for that subpackage. All of the files in the
16 :file:`tests` directory should have the word "tests" in them to enable
16 :file:`tests` directory should have the word "tests" in them to enable
17 the testing framework to find them.
17 the testing framework to find them.
18
18
19 In docstrings, examples (either using IPython prompts like ``In [1]:`` or
19 In docstrings, examples (either using IPython prompts like ``In [1]:`` or
20 'classic' python ``>>>`` ones) can and should be included. The testing system
20 'classic' python ``>>>`` ones) can and should be included. The testing system
21 will detect them as doctests and will run them; it offers control to skip parts
21 will detect them as doctests and will run them; it offers control to skip parts
22 or all of a specific doctest if the example is meant to be informative but
22 or all of a specific doctest if the example is meant to be informative but
23 shows non-reproducible information (like filesystem data).
23 shows non-reproducible information (like filesystem data).
24
24
25 If a subpackage has any dependencies beyond the Python standard library, the
25 If a subpackage has any dependencies beyond the Python standard library, the
26 tests for that subpackage should be skipped if the dependencies are not found.
26 tests for that subpackage should be skipped if the dependencies are not found.
27 This is very important so users don't get tests failing simply because they
27 This is very important so users don't get tests failing simply because they
28 don't have dependencies.
28 don't have dependencies.
29
29
30 The testing system we use is a hybrid of nose_ and Twisted's trial_ test runner.
30 The testing system we use is a hybrid of nose_ and Twisted's trial_ test runner.
31 We use both because nose detects more things than Twisted and allows for more
31 We use both because nose detects more things than Twisted and allows for more
32 flexible (and lighter-weight) ways of writing tests; in particular we've
32 flexible (and lighter-weight) ways of writing tests; in particular we've
33 developed a nose plugin that allows us to paste verbatim IPython sessions and
33 developed a nose plugin that allows us to paste verbatim IPython sessions and
34 test them as doctests, which is extremely important for us. But the parts of
34 test them as doctests, which is extremely important for us. But the parts of
35 IPython that depend on Twisted must be tested using trial, because only trial
35 IPython that depend on Twisted must be tested using trial, because only trial
36 manages the Twisted reactor correctly.
36 manages the Twisted reactor correctly.
37
37
38 .. _nose: http://code.google.com/p/python-nose
38 .. _nose: http://code.google.com/p/python-nose
39 .. _trial: http://twistedmatrix.com/trac/wiki/TwistedTrial
39 .. _trial: http://twistedmatrix.com/trac/wiki/TwistedTrial
40
40
41
41
42 For the impatient: running the tests
42 For the impatient: running the tests
43 ====================================
43 ====================================
44
44
45 You can run IPython from the source download directory without even installing
45 You can run IPython from the source download directory without even installing
46 it system-wide or having configure anything, by typing at the terminal:
46 it system-wide or having configure anything, by typing at the terminal:
47
47
48 .. code-block:: bash
48 .. code-block:: bash
49
49
50 python ipython.py
50 python ipython.py
51
51
52 and similarly, you can execute the built-in test suite with:
52 and similarly, you can execute the built-in test suite with:
53
53
54 .. code-block:: bash
54 .. code-block:: bash
55
55
56 python iptest.py
56 python iptest.py
57
57
58
58
59 This script manages intelligently both nose and trial, choosing the correct
59 This script manages intelligently both nose and trial, choosing the correct
60 test system for each of IPython's components.
60 test system for each of IPython's components.
61
61
62 Once you have either installed it or at least configured your system to be
62 Once you have either installed it or at least configured your system to be
63 able to import IPython, you can run the tests with:
63 able to import IPython, you can run the tests with:
64
64
65 .. code-block:: bash
65 .. code-block:: bash
66
66
67 python -c "import IPython; IPython.test()"
67 python -c "import IPython; IPython.test()"
68
68
69 This should work as long as IPython can be imported, even if you haven't fully
69 This should work as long as IPython can be imported, even if you haven't fully
70 installed the user-facing scripts yet (common in a development environment).
70 installed the user-facing scripts yet (common in a development environment).
71 Once you have installed IPython, you will have available system-wide a script
71 Once you have installed IPython, you will have available system-wide a script
72 called :file:`iptest` that does the exact same as the :file:`iptest.py` script
72 called :file:`iptest` that does the exact same as the :file:`iptest.py` script
73 in the source directory, so you can then test simply with:
73 in the source directory, so you can then test simply with:
74
74
75 .. code-block:: bash
75 .. code-block:: bash
76
76
77 iptest [args]
77 iptest [args]
78
78
79
79
80 Regardless of how you run things, you should eventually see something like:
80 Regardless of how you run things, you should eventually see something like:
81
81
82 .. code-block:: bash
82 .. code-block:: bash
83
83
84 **********************************************************************
84 **********************************************************************
85 Ran 11 test groups in 64.117s
85 Test suite completed for system with the following information:
86 IPython version: 0.11.bzr.r1340
87 BZR revision : 1340
88 Platform info : os.name -> posix, sys.platform -> linux2
89 : Linux-2.6.31-17-generic-i686-with-Ubuntu-9.10-karmic
90 Python info : 2.6.4 (r264:75706, Dec 7 2009, 18:45:15)
91 [GCC 4.4.1]
86
92
87 OK
93 Running from an installed IPython: True
94
95 Tools and libraries available at test time:
96 curses foolscap gobject gtk pexpect twisted wx wx.aui zope.interface
97
98 Tools and libraries NOT available at test time:
99 objc
88
100
101 Ran 11 test groups in 36.244s
102
103 Status:
104 OK
89
105
90 If not, there will be a message indicating which test group failed and how to
106 If not, there will be a message indicating which test group failed and how to
91 rerun that group individually. For example, this tests the
107 rerun that group individually. For example, this tests the
92 :mod:`IPython.utils` subpackage, the :option:`-v` option shows progress
108 :mod:`IPython.utils` subpackage, the :option:`-v` option shows progress
93 indicators:
109 indicators:
94
110
95 .. code-block:: bash
111 .. code-block:: bash
96
112
97 $ python iptest.py -v IPython.utils
113 $ python iptest.py -v IPython.utils
98 ..........................SS..SSS............................S.S...
114 ..........................SS..SSS............................S.S...
99 .........................................................
115 .........................................................
100 ----------------------------------------------------------------------
116 ----------------------------------------------------------------------
101 Ran 125 tests in 0.119s
117 Ran 125 tests in 0.119s
102
118
103 OK (SKIP=7)
119 OK (SKIP=7)
104
120
105
121
106 Because the IPython test machinery is based on nose, you can use all nose
122 Because the IPython test machinery is based on nose, you can use all nose
107 options and syntax, typing ``iptest -h`` shows all available options. For
123 options and syntax, typing ``iptest -h`` shows all available options. For
108 example, this lets you run the specific test :func:`test_rehashx` inside the
124 example, this lets you run the specific test :func:`test_rehashx` inside the
109 :mod:`test_magic` module:
125 :mod:`test_magic` module:
110
126
111 .. code-block:: bash
127 .. code-block:: bash
112
128
113 $ python iptest.py -vv IPython.core.tests.test_magic:test_rehashx
129 $ python iptest.py -vv IPython.core.tests.test_magic:test_rehashx
114 IPython.core.tests.test_magic.test_rehashx(True,) ... ok
130 IPython.core.tests.test_magic.test_rehashx(True,) ... ok
115 IPython.core.tests.test_magic.test_rehashx(True,) ... ok
131 IPython.core.tests.test_magic.test_rehashx(True,) ... ok
116
132
117 ----------------------------------------------------------------------
133 ----------------------------------------------------------------------
118 Ran 2 tests in 0.100s
134 Ran 2 tests in 0.100s
119
135
120 OK
136 OK
121
137
122 When developing, the :option:`--pdb` and :option:`--pdb-failures` of nose are
138 When developing, the :option:`--pdb` and :option:`--pdb-failures` of nose are
123 particularly useful, these drop you into an interactive pdb session at the
139 particularly useful, these drop you into an interactive pdb session at the
124 point of the error or failure respectively.
140 point of the error or failure respectively.
125
141
126 To run Twisted-using tests, use the :command:`trial` command on a per file or
142 To run Twisted-using tests, use the :command:`trial` command on a per file or
127 package basis:
143 package basis:
128
144
129 .. code-block:: bash
145 .. code-block:: bash
130
146
131 trial IPython.kernel
147 trial IPython.kernel
132
148
133
149
134 For developers: writing tests
150 For developers: writing tests
135 =============================
151 =============================
136
152
137 By now IPython has a reasonable test suite, so the best way to see what's
153 By now IPython has a reasonable test suite, so the best way to see what's
138 available is to look at the :file:`tests` directory in most subpackages. But
154 available is to look at the :file:`tests` directory in most subpackages. But
139 here are a few pointers to make the process easier.
155 here are a few pointers to make the process easier.
140
156
141
157
142 Main tools: :mod:`IPython.testing`
158 Main tools: :mod:`IPython.testing`
143 ----------------------------------
159 ----------------------------------
144
160
145 The :mod:`IPython.testing` package is where all of the machinery to test
161 The :mod:`IPython.testing` package is where all of the machinery to test
146 IPython (rather than the tests for its various parts) lives. In particular,
162 IPython (rather than the tests for its various parts) lives. In particular,
147 the :mod:`iptest` module in there has all the smarts to control the test
163 the :mod:`iptest` module in there has all the smarts to control the test
148 process. In there, the :func:`make_exclude` function is used to build a
164 process. In there, the :func:`make_exclude` function is used to build a
149 blacklist of exclusions, these are modules that do not get even imported for
165 blacklist of exclusions, these are modules that do not get even imported for
150 tests. This is important so that things that would fail to even import because
166 tests. This is important so that things that would fail to even import because
151 of missing dependencies don't give errors to end users, as we stated above.
167 of missing dependencies don't give errors to end users, as we stated above.
152
168
153 The :mod:`decorators` module contains a lot of useful decorators, especially
169 The :mod:`decorators` module contains a lot of useful decorators, especially
154 useful to mark individual tests that should be skipped under certain conditions
170 useful to mark individual tests that should be skipped under certain conditions
155 (rather than blacklisting the package altogether because of a missing major
171 (rather than blacklisting the package altogether because of a missing major
156 dependency).
172 dependency).
157
173
158 Our nose plugin for doctests
174 Our nose plugin for doctests
159 ----------------------------
175 ----------------------------
160
176
161 The :mod:`plugin` subpackage in testing contains a nose plugin called
177 The :mod:`plugin` subpackage in testing contains a nose plugin called
162 :mod:`ipdoctest` that teaches nose about IPython syntax, so you can write
178 :mod:`ipdoctest` that teaches nose about IPython syntax, so you can write
163 doctests with IPython prompts. You can also mark doctest output with ``#
179 doctests with IPython prompts. You can also mark doctest output with ``#
164 random`` for the output corresponding to a single input to be ignored (stronger
180 random`` for the output corresponding to a single input to be ignored (stronger
165 than using ellipsis and useful to keep it as an example). If you want the
181 than using ellipsis and useful to keep it as an example). If you want the
166 entire docstring to be executed but none of the output from any input to be
182 entire docstring to be executed but none of the output from any input to be
167 checked, you can use the ``# all-random`` marker. The
183 checked, you can use the ``# all-random`` marker. The
168 :mod:`IPython.testing.plugin.dtexample` module contains examples of how to use
184 :mod:`IPython.testing.plugin.dtexample` module contains examples of how to use
169 these; for reference here is how to use ``# random``::
185 these; for reference here is how to use ``# random``::
170
186
171 def ranfunc():
187 def ranfunc():
172 """A function with some random output.
188 """A function with some random output.
173
189
174 Normal examples are verified as usual:
190 Normal examples are verified as usual:
175 >>> 1+3
191 >>> 1+3
176 4
192 4
177
193
178 But if you put '# random' in the output, it is ignored:
194 But if you put '# random' in the output, it is ignored:
179 >>> 1+3
195 >>> 1+3
180 junk goes here... # random
196 junk goes here... # random
181
197
182 >>> 1+2
198 >>> 1+2
183 again, anything goes #random
199 again, anything goes #random
184 if multiline, the random mark is only needed once.
200 if multiline, the random mark is only needed once.
185
201
186 >>> 1+2
202 >>> 1+2
187 You can also put the random marker at the end:
203 You can also put the random marker at the end:
188 # random
204 # random
189
205
190 >>> 1+2
206 >>> 1+2
191 # random
207 # random
192 .. or at the beginning.
208 .. or at the beginning.
193
209
194 More correct input is properly verified:
210 More correct input is properly verified:
195 >>> ranfunc()
211 >>> ranfunc()
196 'ranfunc'
212 'ranfunc'
197 """
213 """
198 return 'ranfunc'
214 return 'ranfunc'
199
215
200 and an example of ``# all-random``::
216 and an example of ``# all-random``::
201
217
202 def random_all():
218 def random_all():
203 """A function where we ignore the output of ALL examples.
219 """A function where we ignore the output of ALL examples.
204
220
205 Examples:
221 Examples:
206
222
207 # all-random
223 # all-random
208
224
209 This mark tells the testing machinery that all subsequent examples
225 This mark tells the testing machinery that all subsequent examples
210 should be treated as random (ignoring their output). They are still
226 should be treated as random (ignoring their output). They are still
211 executed, so if a they raise an error, it will be detected as such,
227 executed, so if a they raise an error, it will be detected as such,
212 but their output is completely ignored.
228 but their output is completely ignored.
213
229
214 >>> 1+3
230 >>> 1+3
215 junk goes here...
231 junk goes here...
216
232
217 >>> 1+3
233 >>> 1+3
218 klasdfj;
234 klasdfj;
219
235
220 In [8]: print 'hello'
236 In [8]: print 'hello'
221 world # random
237 world # random
222
238
223 In [9]: iprand()
239 In [9]: iprand()
224 Out[9]: 'iprand'
240 Out[9]: 'iprand'
225 """
241 """
226 return 'iprand'
242 return 'iprand'
227
243
228
244
229 When writing docstrings, you can use the ``@skip_doctest`` decorator to
245 When writing docstrings, you can use the ``@skip_doctest`` decorator to
230 indicate that a docstring should *not* be treated as a doctest at all. The
246 indicate that a docstring should *not* be treated as a doctest at all. The
231 difference betwee ``# all-random`` and ``@skip_doctest`` is that the former
247 difference betwee ``# all-random`` and ``@skip_doctest`` is that the former
232 executes the example but ignores output, while the latter doesn't execute any
248 executes the example but ignores output, while the latter doesn't execute any
233 code. ``@skip_doctest`` should be used for docstrings whose examples are
249 code. ``@skip_doctest`` should be used for docstrings whose examples are
234 purely informational.
250 purely informational.
235
251
236 If a given docstring fails under certain conditions but otherwise is a good
252 If a given docstring fails under certain conditions but otherwise is a good
237 doctest, you can use code like the following, that relies on the 'null'
253 doctest, you can use code like the following, that relies on the 'null'
238 decorator to leave the docstring intact where it works as a test::
254 decorator to leave the docstring intact where it works as a test::
239
255
240 # The docstring for full_path doctests differently on win32 (different path
256 # The docstring for full_path doctests differently on win32 (different path
241 # separator) so just skip the doctest there, and use a null decorator
257 # separator) so just skip the doctest there, and use a null decorator
242 # elsewhere:
258 # elsewhere:
243
259
244 doctest_deco = dec.skip_doctest if sys.platform == 'win32' else dec.null_deco
260 doctest_deco = dec.skip_doctest if sys.platform == 'win32' else dec.null_deco
245
261
246 @doctest_deco
262 @doctest_deco
247 def full_path(startPath,files):
263 def full_path(startPath,files):
248 """Make full paths for all the listed files, based on startPath..."""
264 """Make full paths for all the listed files, based on startPath..."""
249
265
250 # function body follows...
266 # function body follows...
251
267
252 With our nose plugin that understands IPython syntax, an extremely effective
268 With our nose plugin that understands IPython syntax, an extremely effective
253 way to write tests is to simply copy and paste an interactive session into a
269 way to write tests is to simply copy and paste an interactive session into a
254 docstring. You can writing this type of test, where your docstring is meant
270 docstring. You can writing this type of test, where your docstring is meant
255 *only* as a test, by prefixing the function name with ``doctest_`` and leaving
271 *only* as a test, by prefixing the function name with ``doctest_`` and leaving
256 its body *absolutely empty* other than the docstring. In
272 its body *absolutely empty* other than the docstring. In
257 :mod:`IPython.core.tests.test_magic` you can find several examples of this, but
273 :mod:`IPython.core.tests.test_magic` you can find several examples of this, but
258 for completeness sake, your code should look like this (a simple case)::
274 for completeness sake, your code should look like this (a simple case)::
259
275
260 def doctest_time():
276 def doctest_time():
261 """
277 """
262 In [10]: %time None
278 In [10]: %time None
263 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
279 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
264 Wall time: 0.00 s
280 Wall time: 0.00 s
265 """
281 """
266
282
267 This function is only analyzed for its docstring but it is not considered a
283 This function is only analyzed for its docstring but it is not considered a
268 separate test, which is why its body should be empty.
284 separate test, which is why its body should be empty.
269
285
270
286
271 Parametric tests done right
287 Parametric tests done right
272 ---------------------------
288 ---------------------------
273
289
274 If you need to run multiple tests inside the same standalone function or method
290 If you need to run multiple tests inside the same standalone function or method
275 of a :class:`unittest.TestCase` subclass, IPython provides the ``parametric``
291 of a :class:`unittest.TestCase` subclass, IPython provides the ``parametric``
276 decorator for this purpose. This is superior to how test generators work in
292 decorator for this purpose. This is superior to how test generators work in
277 nose, because IPython's keeps intact your stack, which makes debugging vastly
293 nose, because IPython's keeps intact your stack, which makes debugging vastly
278 easier. For example, these are some parametric tests both in class form and as
294 easier. For example, these are some parametric tests both in class form and as
279 a standalone function (choose in each situation the style that best fits the
295 a standalone function (choose in each situation the style that best fits the
280 problem at hand, since both work)::
296 problem at hand, since both work)::
281
297
282 from IPython.testing import decorators as dec
298 from IPython.testing import decorators as dec
283
299
284 def is_smaller(i,j):
300 def is_smaller(i,j):
285 assert i<j,"%s !< %s" % (i,j)
301 assert i<j,"%s !< %s" % (i,j)
286
302
287 class Tester(ParametricTestCase):
303 class Tester(ParametricTestCase):
288
304
289 def test_parametric(self):
305 def test_parametric(self):
290 yield is_smaller(3, 4)
306 yield is_smaller(3, 4)
291 x, y = 1, 2
307 x, y = 1, 2
292 yield is_smaller(x, y)
308 yield is_smaller(x, y)
293
309
294 @dec.parametric
310 @dec.parametric
295 def test_par_standalone():
311 def test_par_standalone():
296 yield is_smaller(3, 4)
312 yield is_smaller(3, 4)
297 x, y = 1, 2
313 x, y = 1, 2
298 yield is_smaller(x, y)
314 yield is_smaller(x, y)
299
315
300
316
301 Writing tests for Twisted-using code
317 Writing tests for Twisted-using code
302 ------------------------------------
318 ------------------------------------
303
319
304 Tests of Twisted [Twisted]_ using code should be written by subclassing the
320 Tests of Twisted [Twisted]_ using code should be written by subclassing the
305 ``TestCase`` class that comes with ``twisted.trial.unittest``. Furthermore, all
321 ``TestCase`` class that comes with ``twisted.trial.unittest``. Furthermore, all
306 :class:`Deferred` instances that are created in the test must be properly
322 :class:`Deferred` instances that are created in the test must be properly
307 chained and the final one *must* be the return value of the test method.
323 chained and the final one *must* be the return value of the test method.
308
324
309 .. note::
325 .. note::
310
326
311 The best place to see how to use the testing tools, are the tests for these
327 The best place to see how to use the testing tools, are the tests for these
312 tools themselves, which live in :mod:`IPython.testing.tests`.
328 tools themselves, which live in :mod:`IPython.testing.tests`.
313
329
314
330
315 Design requirements
331 Design requirements
316 ===================
332 ===================
317
333
318 This section is a set of notes on the key points of the IPython testing needs,
334 This section is a set of notes on the key points of the IPython testing needs,
319 that were used when writing the system and should be kept for reference as it
335 that were used when writing the system and should be kept for reference as it
320 eveolves.
336 eveolves.
321
337
322 Testing IPython in full requires modifications to the default behavior of nose
338 Testing IPython in full requires modifications to the default behavior of nose
323 and doctest, because the IPython prompt is not recognized to determine Python
339 and doctest, because the IPython prompt is not recognized to determine Python
324 input, and because IPython admits user input that is not valid Python (things
340 input, and because IPython admits user input that is not valid Python (things
325 like ``%magics`` and ``!system commands``.
341 like ``%magics`` and ``!system commands``.
326
342
327 We basically need to be able to test the following types of code:
343 We basically need to be able to test the following types of code:
328
344
329 1. Pure Python files containing normal tests. These are not a problem, since
345 1. Pure Python files containing normal tests. These are not a problem, since
330 Nose will pick them up as long as they conform to the (flexible) conventions
346 Nose will pick them up as long as they conform to the (flexible) conventions
331 used by nose to recognize tests.
347 used by nose to recognize tests.
332
348
333 2. Python files containing doctests. Here, we have two possibilities:
349 2. Python files containing doctests. Here, we have two possibilities:
334 - The prompts are the usual ``>>>`` and the input is pure Python.
350 - The prompts are the usual ``>>>`` and the input is pure Python.
335 - The prompts are of the form ``In [1]:`` and the input can contain extended
351 - The prompts are of the form ``In [1]:`` and the input can contain extended
336 IPython expressions.
352 IPython expressions.
337
353
338 In the first case, Nose will recognize the doctests as long as it is called
354 In the first case, Nose will recognize the doctests as long as it is called
339 with the ``--with-doctest`` flag. But the second case will likely require
355 with the ``--with-doctest`` flag. But the second case will likely require
340 modifications or the writing of a new doctest plugin for Nose that is
356 modifications or the writing of a new doctest plugin for Nose that is
341 IPython-aware.
357 IPython-aware.
342
358
343 3. ReStructuredText files that contain code blocks. For this type of file, we
359 3. ReStructuredText files that contain code blocks. For this type of file, we
344 have three distinct possibilities for the code blocks:
360 have three distinct possibilities for the code blocks:
345 - They use ``>>>`` prompts.
361 - They use ``>>>`` prompts.
346 - They use ``In [1]:`` prompts.
362 - They use ``In [1]:`` prompts.
347 - They are standalone blocks of pure Python code without any prompts.
363 - They are standalone blocks of pure Python code without any prompts.
348
364
349 The first two cases are similar to the situation #2 above, except that in
365 The first two cases are similar to the situation #2 above, except that in
350 this case the doctests must be extracted from input code blocks using
366 this case the doctests must be extracted from input code blocks using
351 docutils instead of from the Python docstrings.
367 docutils instead of from the Python docstrings.
352
368
353 In the third case, we must have a convention for distinguishing code blocks
369 In the third case, we must have a convention for distinguishing code blocks
354 that are meant for execution from others that may be snippets of shell code
370 that are meant for execution from others that may be snippets of shell code
355 or other examples not meant to be run. One possibility is to assume that
371 or other examples not meant to be run. One possibility is to assume that
356 all indented code blocks are meant for execution, but to have a special
372 all indented code blocks are meant for execution, but to have a special
357 docutils directive for input that should not be executed.
373 docutils directive for input that should not be executed.
358
374
359 For those code blocks that we will execute, the convention used will simply
375 For those code blocks that we will execute, the convention used will simply
360 be that they get called and are considered successful if they run to
376 be that they get called and are considered successful if they run to
361 completion without raising errors. This is similar to what Nose does for
377 completion without raising errors. This is similar to what Nose does for
362 standalone test functions, and by putting asserts or other forms of
378 standalone test functions, and by putting asserts or other forms of
363 exception-raising statements it becomes possible to have literate examples
379 exception-raising statements it becomes possible to have literate examples
364 that double as lightweight tests.
380 that double as lightweight tests.
365
381
366 4. Extension modules with doctests in function and method docstrings.
382 4. Extension modules with doctests in function and method docstrings.
367 Currently Nose simply can't find these docstrings correctly, because the
383 Currently Nose simply can't find these docstrings correctly, because the
368 underlying doctest DocTestFinder object fails there. Similarly to #2 above,
384 underlying doctest DocTestFinder object fails there. Similarly to #2 above,
369 the docstrings could have either pure python or IPython prompts.
385 the docstrings could have either pure python or IPython prompts.
370
386
371 Of these, only 3-c (reST with standalone code blocks) is not implemented at
387 Of these, only 3-c (reST with standalone code blocks) is not implemented at
372 this point.
388 this point.
General Comments 0
You need to be logged in to leave comments. Login now