##// END OF EJS Templates
de-decorate help output tests
MinRK -
Show More
@@ -1,67 +1,55 b''
1 """Test help output of various IPython entry points"""
1 """Test help output of various IPython entry points"""
2
2
3 #-----------------------------------------------------------------------------
3 #-----------------------------------------------------------------------------
4 # Copyright (C) 2013 The IPython Development Team
4 # Copyright (C) 2013 The IPython Development Team
5 #
5 #
6 # Distributed under the terms of the BSD License. The full license is in
6 # Distributed under the terms of the BSD License. The full license is in
7 # the file COPYING, distributed as part of this software.
7 # the file COPYING, distributed as part of this software.
8 #-----------------------------------------------------------------------------
8 #-----------------------------------------------------------------------------
9
9
10 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
11 # Imports
11 # Imports
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13
13
14 from IPython.testing.tools import help, help_all
14 import IPython.testing.tools as tt
15
15
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17 # Tests
17 # Tests
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19
19
20
20
21 @help()
22 def test_ipython_help():
21 def test_ipython_help():
23 pass
22 tt.help_output_test()
24
23
25 @help_all()
26 def test_ipython_help_all():
24 def test_ipython_help_all():
27 pass
25 tt.help_all_output_test()
28
26
29 @help("profile")
30 def test_profile_help():
27 def test_profile_help():
31 pass
28 tt.help_output_test("profile")
32
29
33 @help_all("profile")
34 def test_profile_help_all():
30 def test_profile_help_all():
35 pass
31 tt.help_all_output_test("profile")
36
32
37 @help("profile list")
38 def test_profile_list_help():
33 def test_profile_list_help():
39 pass
34 tt.help_output_test("profile list")
40
35
41 @help_all("profile list")
42 def test_profile_list_help_all():
36 def test_profile_list_help_all():
43 pass
37 tt.help_all_output_test("profile list")
44
38
45 @help("profile create")
46 def test_profile_create_help():
39 def test_profile_create_help():
47 pass
40 tt.help_output_test("profile create")
48
41
49 @help_all("profile create")
50 def test_profile_create_help_all():
42 def test_profile_create_help_all():
51 pass
43 tt.help_all_output_test("profile create")
52
44
53 @help("locate")
54 def test_locate_help():
45 def test_locate_help():
55 pass
46 tt.help_output_test("locate")
56
47
57 @help_all("locate")
58 def test_locate_help_all():
48 def test_locate_help_all():
59 pass
49 tt.help_all_output_test("locate")
60
50
61 @help("locate profile")
62 def test_locate_profile_help():
51 def test_locate_profile_help():
63 pass
52 tt.help_output_test("locate profile")
64
53
65 @help_all("locate profile")
66 def test_locate_profile_all():
54 def test_locate_profile_all():
67 pass
55 tt.help_all_output_test("locate profile")
@@ -1,465 +1,435 b''
1 """Generic testing tools.
1 """Generic testing tools.
2
2
3 Authors
3 Authors
4 -------
4 -------
5 - Fernando Perez <Fernando.Perez@berkeley.edu>
5 - Fernando Perez <Fernando.Perez@berkeley.edu>
6 """
6 """
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
11 # Copyright (C) 2009 The IPython Development Team
11 # Copyright (C) 2009 The IPython Development Team
12 #
12 #
13 # Distributed under the terms of the BSD License. The full license is in
13 # Distributed under the terms of the BSD License. The full license is in
14 # the file COPYING, distributed as part of this software.
14 # the file COPYING, distributed as part of this software.
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16
16
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18 # Imports
18 # Imports
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20
20
21 import inspect
21 import inspect
22 import os
22 import os
23 import re
23 import re
24 import sys
24 import sys
25 import tempfile
25 import tempfile
26
26
27 from contextlib import contextmanager
27 from contextlib import contextmanager
28 from io import StringIO
28 from io import StringIO
29 from subprocess import Popen, PIPE
29 from subprocess import Popen, PIPE
30
30
31 try:
31 try:
32 # These tools are used by parts of the runtime, so we make the nose
32 # These tools are used by parts of the runtime, so we make the nose
33 # dependency optional at this point. Nose is a hard dependency to run the
33 # dependency optional at this point. Nose is a hard dependency to run the
34 # test suite, but NOT to use ipython itself.
34 # test suite, but NOT to use ipython itself.
35 import nose.tools as nt
35 import nose.tools as nt
36 has_nose = True
36 has_nose = True
37 except ImportError:
37 except ImportError:
38 has_nose = False
38 has_nose = False
39
39
40 from IPython.config.loader import Config
40 from IPython.config.loader import Config
41 from IPython.utils.process import get_output_error_code
41 from IPython.utils.process import get_output_error_code
42 from IPython.utils.text import list_strings
42 from IPython.utils.text import list_strings
43 from IPython.utils.io import temp_pyfile, Tee
43 from IPython.utils.io import temp_pyfile, Tee
44 from IPython.utils import py3compat
44 from IPython.utils import py3compat
45 from IPython.utils.encoding import DEFAULT_ENCODING
45 from IPython.utils.encoding import DEFAULT_ENCODING
46
46
47 from . import decorators as dec
47 from . import decorators as dec
48 from . import skipdoctest
48 from . import skipdoctest
49
49
50 #-----------------------------------------------------------------------------
50 #-----------------------------------------------------------------------------
51 # Functions and classes
51 # Functions and classes
52 #-----------------------------------------------------------------------------
52 #-----------------------------------------------------------------------------
53
53
54 # The docstring for full_path doctests differently on win32 (different path
54 # The docstring for full_path doctests differently on win32 (different path
55 # separator) so just skip the doctest there. The example remains informative.
55 # separator) so just skip the doctest there. The example remains informative.
56 doctest_deco = skipdoctest.skip_doctest if sys.platform == 'win32' else dec.null_deco
56 doctest_deco = skipdoctest.skip_doctest if sys.platform == 'win32' else dec.null_deco
57
57
58 @doctest_deco
58 @doctest_deco
59 def full_path(startPath,files):
59 def full_path(startPath,files):
60 """Make full paths for all the listed files, based on startPath.
60 """Make full paths for all the listed files, based on startPath.
61
61
62 Only the base part of startPath is kept, since this routine is typically
62 Only the base part of startPath is kept, since this routine is typically
63 used with a script's __file__ variable as startPath. The base of startPath
63 used with a script's __file__ variable as startPath. The base of startPath
64 is then prepended to all the listed files, forming the output list.
64 is then prepended to all the listed files, forming the output list.
65
65
66 Parameters
66 Parameters
67 ----------
67 ----------
68 startPath : string
68 startPath : string
69 Initial path to use as the base for the results. This path is split
69 Initial path to use as the base for the results. This path is split
70 using os.path.split() and only its first component is kept.
70 using os.path.split() and only its first component is kept.
71
71
72 files : string or list
72 files : string or list
73 One or more files.
73 One or more files.
74
74
75 Examples
75 Examples
76 --------
76 --------
77
77
78 >>> full_path('/foo/bar.py',['a.txt','b.txt'])
78 >>> full_path('/foo/bar.py',['a.txt','b.txt'])
79 ['/foo/a.txt', '/foo/b.txt']
79 ['/foo/a.txt', '/foo/b.txt']
80
80
81 >>> full_path('/foo',['a.txt','b.txt'])
81 >>> full_path('/foo',['a.txt','b.txt'])
82 ['/a.txt', '/b.txt']
82 ['/a.txt', '/b.txt']
83
83
84 If a single file is given, the output is still a list:
84 If a single file is given, the output is still a list:
85 >>> full_path('/foo','a.txt')
85 >>> full_path('/foo','a.txt')
86 ['/a.txt']
86 ['/a.txt']
87 """
87 """
88
88
89 files = list_strings(files)
89 files = list_strings(files)
90 base = os.path.split(startPath)[0]
90 base = os.path.split(startPath)[0]
91 return [ os.path.join(base,f) for f in files ]
91 return [ os.path.join(base,f) for f in files ]
92
92
93
93
94 def parse_test_output(txt):
94 def parse_test_output(txt):
95 """Parse the output of a test run and return errors, failures.
95 """Parse the output of a test run and return errors, failures.
96
96
97 Parameters
97 Parameters
98 ----------
98 ----------
99 txt : str
99 txt : str
100 Text output of a test run, assumed to contain a line of one of the
100 Text output of a test run, assumed to contain a line of one of the
101 following forms::
101 following forms::
102
102
103 'FAILED (errors=1)'
103 'FAILED (errors=1)'
104 'FAILED (failures=1)'
104 'FAILED (failures=1)'
105 'FAILED (errors=1, failures=1)'
105 'FAILED (errors=1, failures=1)'
106
106
107 Returns
107 Returns
108 -------
108 -------
109 nerr, nfail: number of errors and failures.
109 nerr, nfail: number of errors and failures.
110 """
110 """
111
111
112 err_m = re.search(r'^FAILED \(errors=(\d+)\)', txt, re.MULTILINE)
112 err_m = re.search(r'^FAILED \(errors=(\d+)\)', txt, re.MULTILINE)
113 if err_m:
113 if err_m:
114 nerr = int(err_m.group(1))
114 nerr = int(err_m.group(1))
115 nfail = 0
115 nfail = 0
116 return nerr, nfail
116 return nerr, nfail
117
117
118 fail_m = re.search(r'^FAILED \(failures=(\d+)\)', txt, re.MULTILINE)
118 fail_m = re.search(r'^FAILED \(failures=(\d+)\)', txt, re.MULTILINE)
119 if fail_m:
119 if fail_m:
120 nerr = 0
120 nerr = 0
121 nfail = int(fail_m.group(1))
121 nfail = int(fail_m.group(1))
122 return nerr, nfail
122 return nerr, nfail
123
123
124 both_m = re.search(r'^FAILED \(errors=(\d+), failures=(\d+)\)', txt,
124 both_m = re.search(r'^FAILED \(errors=(\d+), failures=(\d+)\)', txt,
125 re.MULTILINE)
125 re.MULTILINE)
126 if both_m:
126 if both_m:
127 nerr = int(both_m.group(1))
127 nerr = int(both_m.group(1))
128 nfail = int(both_m.group(2))
128 nfail = int(both_m.group(2))
129 return nerr, nfail
129 return nerr, nfail
130
130
131 # If the input didn't match any of these forms, assume no error/failures
131 # If the input didn't match any of these forms, assume no error/failures
132 return 0, 0
132 return 0, 0
133
133
134
134
135 # So nose doesn't think this is a test
135 # So nose doesn't think this is a test
136 parse_test_output.__test__ = False
136 parse_test_output.__test__ = False
137
137
138
138
139 def default_argv():
139 def default_argv():
140 """Return a valid default argv for creating testing instances of ipython"""
140 """Return a valid default argv for creating testing instances of ipython"""
141
141
142 return ['--quick', # so no config file is loaded
142 return ['--quick', # so no config file is loaded
143 # Other defaults to minimize side effects on stdout
143 # Other defaults to minimize side effects on stdout
144 '--colors=NoColor', '--no-term-title','--no-banner',
144 '--colors=NoColor', '--no-term-title','--no-banner',
145 '--autocall=0']
145 '--autocall=0']
146
146
147
147
148 def default_config():
148 def default_config():
149 """Return a config object with good defaults for testing."""
149 """Return a config object with good defaults for testing."""
150 config = Config()
150 config = Config()
151 config.TerminalInteractiveShell.colors = 'NoColor'
151 config.TerminalInteractiveShell.colors = 'NoColor'
152 config.TerminalTerminalInteractiveShell.term_title = False,
152 config.TerminalTerminalInteractiveShell.term_title = False,
153 config.TerminalInteractiveShell.autocall = 0
153 config.TerminalInteractiveShell.autocall = 0
154 config.HistoryManager.hist_file = tempfile.mktemp(u'test_hist.sqlite')
154 config.HistoryManager.hist_file = tempfile.mktemp(u'test_hist.sqlite')
155 config.HistoryManager.db_cache_size = 10000
155 config.HistoryManager.db_cache_size = 10000
156 return config
156 return config
157
157
158
158
159 def get_ipython_cmd(as_string=False):
159 def get_ipython_cmd(as_string=False):
160 """
160 """
161 Return appropriate IPython command line name. By default, this will return
161 Return appropriate IPython command line name. By default, this will return
162 a list that can be used with subprocess.Popen, for example, but passing
162 a list that can be used with subprocess.Popen, for example, but passing
163 `as_string=True` allows for returning the IPython command as a string.
163 `as_string=True` allows for returning the IPython command as a string.
164
164
165 Parameters
165 Parameters
166 ----------
166 ----------
167 as_string: bool
167 as_string: bool
168 Flag to allow to return the command as a string.
168 Flag to allow to return the command as a string.
169 """
169 """
170 ipython_cmd = [sys.executable, "-m", "IPython"]
170 ipython_cmd = [sys.executable, "-m", "IPython"]
171
171
172 if as_string:
172 if as_string:
173 ipython_cmd = " ".join(ipython_cmd)
173 ipython_cmd = " ".join(ipython_cmd)
174
174
175 return ipython_cmd
175 return ipython_cmd
176
176
177 def ipexec(fname, options=None):
177 def ipexec(fname, options=None):
178 """Utility to call 'ipython filename'.
178 """Utility to call 'ipython filename'.
179
179
180 Starts IPython with a minimal and safe configuration to make startup as fast
180 Starts IPython with a minimal and safe configuration to make startup as fast
181 as possible.
181 as possible.
182
182
183 Note that this starts IPython in a subprocess!
183 Note that this starts IPython in a subprocess!
184
184
185 Parameters
185 Parameters
186 ----------
186 ----------
187 fname : str
187 fname : str
188 Name of file to be executed (should have .py or .ipy extension).
188 Name of file to be executed (should have .py or .ipy extension).
189
189
190 options : optional, list
190 options : optional, list
191 Extra command-line flags to be passed to IPython.
191 Extra command-line flags to be passed to IPython.
192
192
193 Returns
193 Returns
194 -------
194 -------
195 (stdout, stderr) of ipython subprocess.
195 (stdout, stderr) of ipython subprocess.
196 """
196 """
197 if options is None: options = []
197 if options is None: options = []
198
198
199 # For these subprocess calls, eliminate all prompt printing so we only see
199 # For these subprocess calls, eliminate all prompt printing so we only see
200 # output from script execution
200 # output from script execution
201 prompt_opts = [ '--PromptManager.in_template=""',
201 prompt_opts = [ '--PromptManager.in_template=""',
202 '--PromptManager.in2_template=""',
202 '--PromptManager.in2_template=""',
203 '--PromptManager.out_template=""'
203 '--PromptManager.out_template=""'
204 ]
204 ]
205 cmdargs = default_argv() + prompt_opts + options
205 cmdargs = default_argv() + prompt_opts + options
206
206
207 test_dir = os.path.dirname(__file__)
207 test_dir = os.path.dirname(__file__)
208
208
209 ipython_cmd = get_ipython_cmd()
209 ipython_cmd = get_ipython_cmd()
210 # Absolute path for filename
210 # Absolute path for filename
211 full_fname = os.path.join(test_dir, fname)
211 full_fname = os.path.join(test_dir, fname)
212 full_cmd = ipython_cmd + cmdargs + [full_fname]
212 full_cmd = ipython_cmd + cmdargs + [full_fname]
213 p = Popen(full_cmd, stdout=PIPE, stderr=PIPE)
213 p = Popen(full_cmd, stdout=PIPE, stderr=PIPE)
214 out, err = p.communicate()
214 out, err = p.communicate()
215 out, err = py3compat.bytes_to_str(out), py3compat.bytes_to_str(err)
215 out, err = py3compat.bytes_to_str(out), py3compat.bytes_to_str(err)
216 # `import readline` causes 'ESC[?1034h' to be output sometimes,
216 # `import readline` causes 'ESC[?1034h' to be output sometimes,
217 # so strip that out before doing comparisons
217 # so strip that out before doing comparisons
218 if out:
218 if out:
219 out = re.sub(r'\x1b\[[^h]+h', '', out)
219 out = re.sub(r'\x1b\[[^h]+h', '', out)
220 return out, err
220 return out, err
221
221
222
222
223 def ipexec_validate(fname, expected_out, expected_err='',
223 def ipexec_validate(fname, expected_out, expected_err='',
224 options=None):
224 options=None):
225 """Utility to call 'ipython filename' and validate output/error.
225 """Utility to call 'ipython filename' and validate output/error.
226
226
227 This function raises an AssertionError if the validation fails.
227 This function raises an AssertionError if the validation fails.
228
228
229 Note that this starts IPython in a subprocess!
229 Note that this starts IPython in a subprocess!
230
230
231 Parameters
231 Parameters
232 ----------
232 ----------
233 fname : str
233 fname : str
234 Name of the file to be executed (should have .py or .ipy extension).
234 Name of the file to be executed (should have .py or .ipy extension).
235
235
236 expected_out : str
236 expected_out : str
237 Expected stdout of the process.
237 Expected stdout of the process.
238
238
239 expected_err : optional, str
239 expected_err : optional, str
240 Expected stderr of the process.
240 Expected stderr of the process.
241
241
242 options : optional, list
242 options : optional, list
243 Extra command-line flags to be passed to IPython.
243 Extra command-line flags to be passed to IPython.
244
244
245 Returns
245 Returns
246 -------
246 -------
247 None
247 None
248 """
248 """
249
249
250 import nose.tools as nt
250 import nose.tools as nt
251
251
252 out, err = ipexec(fname, options)
252 out, err = ipexec(fname, options)
253 #print 'OUT', out # dbg
253 #print 'OUT', out # dbg
254 #print 'ERR', err # dbg
254 #print 'ERR', err # dbg
255 # If there are any errors, we must check those befor stdout, as they may be
255 # If there are any errors, we must check those befor stdout, as they may be
256 # more informative than simply having an empty stdout.
256 # more informative than simply having an empty stdout.
257 if err:
257 if err:
258 if expected_err:
258 if expected_err:
259 nt.assert_equal("\n".join(err.strip().splitlines()), "\n".join(expected_err.strip().splitlines()))
259 nt.assert_equal("\n".join(err.strip().splitlines()), "\n".join(expected_err.strip().splitlines()))
260 else:
260 else:
261 raise ValueError('Running file %r produced error: %r' %
261 raise ValueError('Running file %r produced error: %r' %
262 (fname, err))
262 (fname, err))
263 # If no errors or output on stderr was expected, match stdout
263 # If no errors or output on stderr was expected, match stdout
264 nt.assert_equal("\n".join(out.strip().splitlines()), "\n".join(expected_out.strip().splitlines()))
264 nt.assert_equal("\n".join(out.strip().splitlines()), "\n".join(expected_out.strip().splitlines()))
265
265
266
266
267 class TempFileMixin(object):
267 class TempFileMixin(object):
268 """Utility class to create temporary Python/IPython files.
268 """Utility class to create temporary Python/IPython files.
269
269
270 Meant as a mixin class for test cases."""
270 Meant as a mixin class for test cases."""
271
271
272 def mktmp(self, src, ext='.py'):
272 def mktmp(self, src, ext='.py'):
273 """Make a valid python temp file."""
273 """Make a valid python temp file."""
274 fname, f = temp_pyfile(src, ext)
274 fname, f = temp_pyfile(src, ext)
275 self.tmpfile = f
275 self.tmpfile = f
276 self.fname = fname
276 self.fname = fname
277
277
278 def tearDown(self):
278 def tearDown(self):
279 if hasattr(self, 'tmpfile'):
279 if hasattr(self, 'tmpfile'):
280 # If the tmpfile wasn't made because of skipped tests, like in
280 # If the tmpfile wasn't made because of skipped tests, like in
281 # win32, there's nothing to cleanup.
281 # win32, there's nothing to cleanup.
282 self.tmpfile.close()
282 self.tmpfile.close()
283 try:
283 try:
284 os.unlink(self.fname)
284 os.unlink(self.fname)
285 except:
285 except:
286 # On Windows, even though we close the file, we still can't
286 # On Windows, even though we close the file, we still can't
287 # delete it. I have no clue why
287 # delete it. I have no clue why
288 pass
288 pass
289
289
290 pair_fail_msg = ("Testing {0}\n\n"
290 pair_fail_msg = ("Testing {0}\n\n"
291 "In:\n"
291 "In:\n"
292 " {1!r}\n"
292 " {1!r}\n"
293 "Expected:\n"
293 "Expected:\n"
294 " {2!r}\n"
294 " {2!r}\n"
295 "Got:\n"
295 "Got:\n"
296 " {3!r}\n")
296 " {3!r}\n")
297 def check_pairs(func, pairs):
297 def check_pairs(func, pairs):
298 """Utility function for the common case of checking a function with a
298 """Utility function for the common case of checking a function with a
299 sequence of input/output pairs.
299 sequence of input/output pairs.
300
300
301 Parameters
301 Parameters
302 ----------
302 ----------
303 func : callable
303 func : callable
304 The function to be tested. Should accept a single argument.
304 The function to be tested. Should accept a single argument.
305 pairs : iterable
305 pairs : iterable
306 A list of (input, expected_output) tuples.
306 A list of (input, expected_output) tuples.
307
307
308 Returns
308 Returns
309 -------
309 -------
310 None. Raises an AssertionError if any output does not match the expected
310 None. Raises an AssertionError if any output does not match the expected
311 value.
311 value.
312 """
312 """
313 name = getattr(func, "func_name", getattr(func, "__name__", "<unknown>"))
313 name = getattr(func, "func_name", getattr(func, "__name__", "<unknown>"))
314 for inp, expected in pairs:
314 for inp, expected in pairs:
315 out = func(inp)
315 out = func(inp)
316 assert out == expected, pair_fail_msg.format(name, inp, expected, out)
316 assert out == expected, pair_fail_msg.format(name, inp, expected, out)
317
317
318
318
319 if py3compat.PY3:
319 if py3compat.PY3:
320 MyStringIO = StringIO
320 MyStringIO = StringIO
321 else:
321 else:
322 # In Python 2, stdout/stderr can have either bytes or unicode written to them,
322 # In Python 2, stdout/stderr can have either bytes or unicode written to them,
323 # so we need a class that can handle both.
323 # so we need a class that can handle both.
324 class MyStringIO(StringIO):
324 class MyStringIO(StringIO):
325 def write(self, s):
325 def write(self, s):
326 s = py3compat.cast_unicode(s, encoding=DEFAULT_ENCODING)
326 s = py3compat.cast_unicode(s, encoding=DEFAULT_ENCODING)
327 super(MyStringIO, self).write(s)
327 super(MyStringIO, self).write(s)
328
328
329 notprinted_msg = """Did not find {0!r} in printed output (on {1}):
329 notprinted_msg = """Did not find {0!r} in printed output (on {1}):
330 -------
330 -------
331 {2!s}
331 {2!s}
332 -------
332 -------
333 """
333 """
334
334
335 class AssertPrints(object):
335 class AssertPrints(object):
336 """Context manager for testing that code prints certain text.
336 """Context manager for testing that code prints certain text.
337
337
338 Examples
338 Examples
339 --------
339 --------
340 >>> with AssertPrints("abc", suppress=False):
340 >>> with AssertPrints("abc", suppress=False):
341 ... print "abcd"
341 ... print "abcd"
342 ... print "def"
342 ... print "def"
343 ...
343 ...
344 abcd
344 abcd
345 def
345 def
346 """
346 """
347 def __init__(self, s, channel='stdout', suppress=True):
347 def __init__(self, s, channel='stdout', suppress=True):
348 self.s = s
348 self.s = s
349 self.channel = channel
349 self.channel = channel
350 self.suppress = suppress
350 self.suppress = suppress
351
351
352 def __enter__(self):
352 def __enter__(self):
353 self.orig_stream = getattr(sys, self.channel)
353 self.orig_stream = getattr(sys, self.channel)
354 self.buffer = MyStringIO()
354 self.buffer = MyStringIO()
355 self.tee = Tee(self.buffer, channel=self.channel)
355 self.tee = Tee(self.buffer, channel=self.channel)
356 setattr(sys, self.channel, self.buffer if self.suppress else self.tee)
356 setattr(sys, self.channel, self.buffer if self.suppress else self.tee)
357
357
358 def __exit__(self, etype, value, traceback):
358 def __exit__(self, etype, value, traceback):
359 self.tee.flush()
359 self.tee.flush()
360 setattr(sys, self.channel, self.orig_stream)
360 setattr(sys, self.channel, self.orig_stream)
361 printed = self.buffer.getvalue()
361 printed = self.buffer.getvalue()
362 assert self.s in printed, notprinted_msg.format(self.s, self.channel, printed)
362 assert self.s in printed, notprinted_msg.format(self.s, self.channel, printed)
363 return False
363 return False
364
364
365 printed_msg = """Found {0!r} in printed output (on {1}):
365 printed_msg = """Found {0!r} in printed output (on {1}):
366 -------
366 -------
367 {2!s}
367 {2!s}
368 -------
368 -------
369 """
369 """
370
370
371 class AssertNotPrints(AssertPrints):
371 class AssertNotPrints(AssertPrints):
372 """Context manager for checking that certain output *isn't* produced.
372 """Context manager for checking that certain output *isn't* produced.
373
373
374 Counterpart of AssertPrints"""
374 Counterpart of AssertPrints"""
375 def __exit__(self, etype, value, traceback):
375 def __exit__(self, etype, value, traceback):
376 self.tee.flush()
376 self.tee.flush()
377 setattr(sys, self.channel, self.orig_stream)
377 setattr(sys, self.channel, self.orig_stream)
378 printed = self.buffer.getvalue()
378 printed = self.buffer.getvalue()
379 assert self.s not in printed, printed_msg.format(self.s, self.channel, printed)
379 assert self.s not in printed, printed_msg.format(self.s, self.channel, printed)
380 return False
380 return False
381
381
382 @contextmanager
382 @contextmanager
383 def mute_warn():
383 def mute_warn():
384 from IPython.utils import warn
384 from IPython.utils import warn
385 save_warn = warn.warn
385 save_warn = warn.warn
386 warn.warn = lambda *a, **kw: None
386 warn.warn = lambda *a, **kw: None
387 try:
387 try:
388 yield
388 yield
389 finally:
389 finally:
390 warn.warn = save_warn
390 warn.warn = save_warn
391
391
392 @contextmanager
392 @contextmanager
393 def make_tempfile(name):
393 def make_tempfile(name):
394 """ Create an empty, named, temporary file for the duration of the context.
394 """ Create an empty, named, temporary file for the duration of the context.
395 """
395 """
396 f = open(name, 'w')
396 f = open(name, 'w')
397 f.close()
397 f.close()
398 try:
398 try:
399 yield
399 yield
400 finally:
400 finally:
401 os.unlink(name)
401 os.unlink(name)
402
402
403
403
404 @contextmanager
404 @contextmanager
405 def monkeypatch(obj, name, attr):
405 def monkeypatch(obj, name, attr):
406 """
406 """
407 Context manager to replace attribute named `name` in `obj` with `attr`.
407 Context manager to replace attribute named `name` in `obj` with `attr`.
408 """
408 """
409 orig = getattr(obj, name)
409 orig = getattr(obj, name)
410 setattr(obj, name, attr)
410 setattr(obj, name, attr)
411 yield
411 yield
412 setattr(obj, name, orig)
412 setattr(obj, name, orig)
413
413
414
414
415 def help_output_test(subcommand=''):
415 def help_output_test(subcommand=''):
416 """test that `ipython [subcommand] -h` works"""
416 """test that `ipython [subcommand] -h` works"""
417 cmd = ' '.join(get_ipython_cmd() + [subcommand, '-h'])
417 cmd = ' '.join(get_ipython_cmd() + [subcommand, '-h'])
418 out, err, rc = get_output_error_code(cmd)
418 out, err, rc = get_output_error_code(cmd)
419 nt.assert_equal(rc, 0, err)
419 nt.assert_equal(rc, 0, err)
420 nt.assert_not_in("Traceback", err)
420 nt.assert_not_in("Traceback", err)
421 nt.assert_in("Options", out)
421 nt.assert_in("Options", out)
422 nt.assert_in("--help-all", out)
422 nt.assert_in("--help-all", out)
423 return out, err
423 return out, err
424
424
425
425
426 def help_all_output_test(subcommand=''):
426 def help_all_output_test(subcommand=''):
427 """test that `ipython [subcommand] --help-all` works"""
427 """test that `ipython [subcommand] --help-all` works"""
428 cmd = ' '.join(get_ipython_cmd() + [subcommand, '--help-all'])
428 cmd = ' '.join(get_ipython_cmd() + [subcommand, '--help-all'])
429 out, err, rc = get_output_error_code(cmd)
429 out, err, rc = get_output_error_code(cmd)
430 nt.assert_equal(rc, 0, err)
430 nt.assert_equal(rc, 0, err)
431 nt.assert_not_in("Traceback", err)
431 nt.assert_not_in("Traceback", err)
432 nt.assert_in("Options", out)
432 nt.assert_in("Options", out)
433 nt.assert_in("Class parameters", out)
433 nt.assert_in("Class parameters", out)
434 return out, err
434 return out, err
435
435
436
437 def help(cmd=''):
438 """decorator for making a test for `ipython cmd -h`"""
439 def wrap_help_test(f):
440 def test_help_output():
441 out, err = help_output_test(cmd)
442 if inspect.getargspec(f).args:
443 return f(out, err)
444 else:
445 return f()
446 cmds = cmd + ' ' if cmd else ''
447 test_help_output.__doc__ = "ipython {cmds}--help-all works".format(cmds=cmds)
448
449 return test_help_output
450 return wrap_help_test
451
452
453 def help_all(cmd=''):
454 """decorator for making a test for `ipython [cmd] --help-all`"""
455 def wrap_help_test(f):
456 def test_help_output():
457 out, err = help_all_output_test(cmd)
458 if inspect.getargspec(f).args:
459 return f(out, err)
460 else:
461 return f()
462 cmds = cmd + ' ' if cmd else ''
463 test_help_output.__doc__ = "ipython {cmds}--help-all works".format(cmds=cmds)
464 return test_help_output
465 return wrap_help_test
General Comments 0
You need to be logged in to leave comments. Login now