##// END OF EJS Templates
catch up tests to recent changes...
MinRK -
Show More
@@ -1,164 +1,166 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 """
3 """
4 Tests for IPython.config.configurable
4 Tests for IPython.config.configurable
5
5
6 Authors:
6 Authors:
7
7
8 * Brian Granger
8 * Brian Granger
9 * Fernando Perez (design help)
9 * Fernando Perez (design help)
10 """
10 """
11
11
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13 # Copyright (C) 2008-2010 The IPython Development Team
13 # Copyright (C) 2008-2010 The IPython Development Team
14 #
14 #
15 # Distributed under the terms of the BSD License. The full license is in
15 # Distributed under the terms of the BSD License. The full license is in
16 # the file COPYING, distributed as part of this software.
16 # the file COPYING, distributed as part of this software.
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18
18
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20 # Imports
20 # Imports
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22
22
23 from unittest import TestCase
23 from unittest import TestCase
24
24
25 from IPython.config.configurable import (
25 from IPython.config.configurable import (
26 Configurable,
26 Configurable,
27 SingletonConfigurable
27 SingletonConfigurable
28 )
28 )
29
29
30 from IPython.utils.traitlets import (
30 from IPython.utils.traitlets import (
31 Int, Float, Str
31 Int, Float, Str
32 )
32 )
33
33
34 from IPython.config.loader import Config
34 from IPython.config.loader import Config
35
35
36
36
37 #-----------------------------------------------------------------------------
37 #-----------------------------------------------------------------------------
38 # Test cases
38 # Test cases
39 #-----------------------------------------------------------------------------
39 #-----------------------------------------------------------------------------
40
40
41
41
42 class MyConfigurable(Configurable):
42 class MyConfigurable(Configurable):
43 a = Int(1, config=True, help="The integer a.")
43 a = Int(1, config=True, help="The integer a.")
44 b = Float(1.0, config=True, help="The integer b.")
44 b = Float(1.0, config=True, help="The integer b.")
45 c = Str('no config')
45 c = Str('no config')
46
46
47
47
48 mc_help=u"""MyConfigurable options
48 mc_help=u"""MyConfigurable options
49 ----------------------
49 ----------------------
50 MyConfigurable.a : Int [default: 1]
50 MyConfigurable.a : Int
51 Default: 1
51 The integer a.
52 The integer a.
52 MyConfigurable.b : Float [default: 1.0]
53 MyConfigurable.b : Float
54 Default: 1.0
53 The integer b."""
55 The integer b."""
54
56
55 class Foo(Configurable):
57 class Foo(Configurable):
56 a = Int(0, config=True, help="The integer a.")
58 a = Int(0, config=True, help="The integer a.")
57 b = Str('nope', config=True)
59 b = Str('nope', config=True)
58
60
59
61
60 class Bar(Foo):
62 class Bar(Foo):
61 b = Str('gotit', config=False, help="The string b.")
63 b = Str('gotit', config=False, help="The string b.")
62 c = Float(config=True, help="The string c.")
64 c = Float(config=True, help="The string c.")
63
65
64
66
65 class TestConfigurable(TestCase):
67 class TestConfigurable(TestCase):
66
68
67 def test_default(self):
69 def test_default(self):
68 c1 = Configurable()
70 c1 = Configurable()
69 c2 = Configurable(config=c1.config)
71 c2 = Configurable(config=c1.config)
70 c3 = Configurable(config=c2.config)
72 c3 = Configurable(config=c2.config)
71 self.assertEquals(c1.config, c2.config)
73 self.assertEquals(c1.config, c2.config)
72 self.assertEquals(c2.config, c3.config)
74 self.assertEquals(c2.config, c3.config)
73
75
74 def test_custom(self):
76 def test_custom(self):
75 config = Config()
77 config = Config()
76 config.foo = 'foo'
78 config.foo = 'foo'
77 config.bar = 'bar'
79 config.bar = 'bar'
78 c1 = Configurable(config=config)
80 c1 = Configurable(config=config)
79 c2 = Configurable(config=c1.config)
81 c2 = Configurable(config=c1.config)
80 c3 = Configurable(config=c2.config)
82 c3 = Configurable(config=c2.config)
81 self.assertEquals(c1.config, config)
83 self.assertEquals(c1.config, config)
82 self.assertEquals(c2.config, config)
84 self.assertEquals(c2.config, config)
83 self.assertEquals(c3.config, config)
85 self.assertEquals(c3.config, config)
84 # Test that copies are not made
86 # Test that copies are not made
85 self.assert_(c1.config is config)
87 self.assert_(c1.config is config)
86 self.assert_(c2.config is config)
88 self.assert_(c2.config is config)
87 self.assert_(c3.config is config)
89 self.assert_(c3.config is config)
88 self.assert_(c1.config is c2.config)
90 self.assert_(c1.config is c2.config)
89 self.assert_(c2.config is c3.config)
91 self.assert_(c2.config is c3.config)
90
92
91 def test_inheritance(self):
93 def test_inheritance(self):
92 config = Config()
94 config = Config()
93 config.MyConfigurable.a = 2
95 config.MyConfigurable.a = 2
94 config.MyConfigurable.b = 2.0
96 config.MyConfigurable.b = 2.0
95 c1 = MyConfigurable(config=config)
97 c1 = MyConfigurable(config=config)
96 c2 = MyConfigurable(config=c1.config)
98 c2 = MyConfigurable(config=c1.config)
97 self.assertEquals(c1.a, config.MyConfigurable.a)
99 self.assertEquals(c1.a, config.MyConfigurable.a)
98 self.assertEquals(c1.b, config.MyConfigurable.b)
100 self.assertEquals(c1.b, config.MyConfigurable.b)
99 self.assertEquals(c2.a, config.MyConfigurable.a)
101 self.assertEquals(c2.a, config.MyConfigurable.a)
100 self.assertEquals(c2.b, config.MyConfigurable.b)
102 self.assertEquals(c2.b, config.MyConfigurable.b)
101
103
102 def test_parent(self):
104 def test_parent(self):
103 config = Config()
105 config = Config()
104 config.Foo.a = 10
106 config.Foo.a = 10
105 config.Foo.b = "wow"
107 config.Foo.b = "wow"
106 config.Bar.b = 'later'
108 config.Bar.b = 'later'
107 config.Bar.c = 100.0
109 config.Bar.c = 100.0
108 f = Foo(config=config)
110 f = Foo(config=config)
109 b = Bar(config=f.config)
111 b = Bar(config=f.config)
110 self.assertEquals(f.a, 10)
112 self.assertEquals(f.a, 10)
111 self.assertEquals(f.b, 'wow')
113 self.assertEquals(f.b, 'wow')
112 self.assertEquals(b.b, 'gotit')
114 self.assertEquals(b.b, 'gotit')
113 self.assertEquals(b.c, 100.0)
115 self.assertEquals(b.c, 100.0)
114
116
115 def test_override1(self):
117 def test_override1(self):
116 config = Config()
118 config = Config()
117 config.MyConfigurable.a = 2
119 config.MyConfigurable.a = 2
118 config.MyConfigurable.b = 2.0
120 config.MyConfigurable.b = 2.0
119 c = MyConfigurable(a=3, config=config)
121 c = MyConfigurable(a=3, config=config)
120 self.assertEquals(c.a, 3)
122 self.assertEquals(c.a, 3)
121 self.assertEquals(c.b, config.MyConfigurable.b)
123 self.assertEquals(c.b, config.MyConfigurable.b)
122 self.assertEquals(c.c, 'no config')
124 self.assertEquals(c.c, 'no config')
123
125
124 def test_override2(self):
126 def test_override2(self):
125 config = Config()
127 config = Config()
126 config.Foo.a = 1
128 config.Foo.a = 1
127 config.Bar.b = 'or' # Up above b is config=False, so this won't do it.
129 config.Bar.b = 'or' # Up above b is config=False, so this won't do it.
128 config.Bar.c = 10.0
130 config.Bar.c = 10.0
129 c = Bar(config=config)
131 c = Bar(config=config)
130 self.assertEquals(c.a, config.Foo.a)
132 self.assertEquals(c.a, config.Foo.a)
131 self.assertEquals(c.b, 'gotit')
133 self.assertEquals(c.b, 'gotit')
132 self.assertEquals(c.c, config.Bar.c)
134 self.assertEquals(c.c, config.Bar.c)
133 c = Bar(a=2, b='and', c=20.0, config=config)
135 c = Bar(a=2, b='and', c=20.0, config=config)
134 self.assertEquals(c.a, 2)
136 self.assertEquals(c.a, 2)
135 self.assertEquals(c.b, 'and')
137 self.assertEquals(c.b, 'and')
136 self.assertEquals(c.c, 20.0)
138 self.assertEquals(c.c, 20.0)
137
139
138 def test_help(self):
140 def test_help(self):
139 self.assertEquals(MyConfigurable.class_get_help(), mc_help)
141 self.assertEquals(MyConfigurable.class_get_help(), mc_help)
140
142
141
143
142 class TestSingletonConfigurable(TestCase):
144 class TestSingletonConfigurable(TestCase):
143
145
144 def test_instance(self):
146 def test_instance(self):
145 from IPython.config.configurable import SingletonConfigurable
147 from IPython.config.configurable import SingletonConfigurable
146 class Foo(SingletonConfigurable): pass
148 class Foo(SingletonConfigurable): pass
147 self.assertEquals(Foo.initialized(), False)
149 self.assertEquals(Foo.initialized(), False)
148 foo = Foo.instance()
150 foo = Foo.instance()
149 self.assertEquals(Foo.initialized(), True)
151 self.assertEquals(Foo.initialized(), True)
150 self.assertEquals(foo, Foo.instance())
152 self.assertEquals(foo, Foo.instance())
151 self.assertEquals(SingletonConfigurable._instance, None)
153 self.assertEquals(SingletonConfigurable._instance, None)
152
154
153 def test_inheritance(self):
155 def test_inheritance(self):
154 class Bar(SingletonConfigurable): pass
156 class Bar(SingletonConfigurable): pass
155 class Bam(Bar): pass
157 class Bam(Bar): pass
156 self.assertEquals(Bar.initialized(), False)
158 self.assertEquals(Bar.initialized(), False)
157 self.assertEquals(Bam.initialized(), False)
159 self.assertEquals(Bam.initialized(), False)
158 bam = Bam.instance()
160 bam = Bam.instance()
159 bam == Bar.instance()
161 bam == Bar.instance()
160 self.assertEquals(Bar.initialized(), True)
162 self.assertEquals(Bar.initialized(), True)
161 self.assertEquals(Bam.initialized(), True)
163 self.assertEquals(Bam.initialized(), True)
162 self.assertEquals(bam, Bam._instance)
164 self.assertEquals(bam, Bam._instance)
163 self.assertEquals(bam, Bar._instance)
165 self.assertEquals(bam, Bar._instance)
164 self.assertEquals(SingletonConfigurable._instance, None)
166 self.assertEquals(SingletonConfigurable._instance, None)
@@ -1,280 +1,283 b''
1 """Generic testing tools that do NOT depend on Twisted.
1 """Generic testing tools that do NOT depend on Twisted.
2
2
3 In particular, this module exposes a set of top-level assert* functions that
3 In particular, this module exposes a set of top-level assert* functions that
4 can be used in place of nose.tools.assert* in method generators (the ones in
4 can be used in place of nose.tools.assert* in method generators (the ones in
5 nose can not, at least as of nose 0.10.4).
5 nose can not, at least as of nose 0.10.4).
6
6
7 Note: our testing package contains testing.util, which does depend on Twisted
7 Note: our testing package contains testing.util, which does depend on Twisted
8 and provides utilities for tests that manage Deferreds. All testing support
8 and provides utilities for tests that manage Deferreds. All testing support
9 tools that only depend on nose, IPython or the standard library should go here
9 tools that only depend on nose, IPython or the standard library should go here
10 instead.
10 instead.
11
11
12
12
13 Authors
13 Authors
14 -------
14 -------
15 - Fernando Perez <Fernando.Perez@berkeley.edu>
15 - Fernando Perez <Fernando.Perez@berkeley.edu>
16 """
16 """
17
17
18 from __future__ import absolute_import
18 from __future__ import absolute_import
19
19
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21 # Copyright (C) 2009 The IPython Development Team
21 # Copyright (C) 2009 The IPython Development Team
22 #
22 #
23 # Distributed under the terms of the BSD License. The full license is in
23 # Distributed under the terms of the BSD License. The full license is in
24 # the file COPYING, distributed as part of this software.
24 # the file COPYING, distributed as part of this software.
25 #-----------------------------------------------------------------------------
25 #-----------------------------------------------------------------------------
26
26
27 #-----------------------------------------------------------------------------
27 #-----------------------------------------------------------------------------
28 # Imports
28 # Imports
29 #-----------------------------------------------------------------------------
29 #-----------------------------------------------------------------------------
30
30
31 import os
31 import os
32 import re
32 import re
33 import sys
33 import sys
34
34
35 try:
35 try:
36 # These tools are used by parts of the runtime, so we make the nose
36 # These tools are used by parts of the runtime, so we make the nose
37 # dependency optional at this point. Nose is a hard dependency to run the
37 # dependency optional at this point. Nose is a hard dependency to run the
38 # test suite, but NOT to use ipython itself.
38 # test suite, but NOT to use ipython itself.
39 import nose.tools as nt
39 import nose.tools as nt
40 has_nose = True
40 has_nose = True
41 except ImportError:
41 except ImportError:
42 has_nose = False
42 has_nose = False
43
43
44 from IPython.config.loader import Config
44 from IPython.config.loader import Config
45 from IPython.utils.process import find_cmd, getoutputerror
45 from IPython.utils.process import find_cmd, getoutputerror
46 from IPython.utils.text import list_strings
46 from IPython.utils.text import list_strings
47 from IPython.utils.io import temp_pyfile
47 from IPython.utils.io import temp_pyfile
48
48
49 from . import decorators as dec
49 from . import decorators as dec
50 from . import skipdoctest
50 from . import skipdoctest
51
51
52 #-----------------------------------------------------------------------------
52 #-----------------------------------------------------------------------------
53 # Globals
53 # Globals
54 #-----------------------------------------------------------------------------
54 #-----------------------------------------------------------------------------
55
55
56 # Make a bunch of nose.tools assert wrappers that can be used in test
56 # Make a bunch of nose.tools assert wrappers that can be used in test
57 # generators. This will expose an assert* function for each one in nose.tools.
57 # generators. This will expose an assert* function for each one in nose.tools.
58
58
59 _tpl = """
59 _tpl = """
60 def %(name)s(*a,**kw):
60 def %(name)s(*a,**kw):
61 return nt.%(name)s(*a,**kw)
61 return nt.%(name)s(*a,**kw)
62 """
62 """
63
63
64 if has_nose:
64 if has_nose:
65 for _x in [a for a in dir(nt) if a.startswith('assert')]:
65 for _x in [a for a in dir(nt) if a.startswith('assert')]:
66 exec _tpl % dict(name=_x)
66 exec _tpl % dict(name=_x)
67
67
68 #-----------------------------------------------------------------------------
68 #-----------------------------------------------------------------------------
69 # Functions and classes
69 # Functions and classes
70 #-----------------------------------------------------------------------------
70 #-----------------------------------------------------------------------------
71
71
72 # The docstring for full_path doctests differently on win32 (different path
72 # The docstring for full_path doctests differently on win32 (different path
73 # separator) so just skip the doctest there. The example remains informative.
73 # separator) so just skip the doctest there. The example remains informative.
74 doctest_deco = skipdoctest.skip_doctest if sys.platform == 'win32' else dec.null_deco
74 doctest_deco = skipdoctest.skip_doctest if sys.platform == 'win32' else dec.null_deco
75
75
76 @doctest_deco
76 @doctest_deco
77 def full_path(startPath,files):
77 def full_path(startPath,files):
78 """Make full paths for all the listed files, based on startPath.
78 """Make full paths for all the listed files, based on startPath.
79
79
80 Only the base part of startPath is kept, since this routine is typically
80 Only the base part of startPath is kept, since this routine is typically
81 used with a script's __file__ variable as startPath. The base of startPath
81 used with a script's __file__ variable as startPath. The base of startPath
82 is then prepended to all the listed files, forming the output list.
82 is then prepended to all the listed files, forming the output list.
83
83
84 Parameters
84 Parameters
85 ----------
85 ----------
86 startPath : string
86 startPath : string
87 Initial path to use as the base for the results. This path is split
87 Initial path to use as the base for the results. This path is split
88 using os.path.split() and only its first component is kept.
88 using os.path.split() and only its first component is kept.
89
89
90 files : string or list
90 files : string or list
91 One or more files.
91 One or more files.
92
92
93 Examples
93 Examples
94 --------
94 --------
95
95
96 >>> full_path('/foo/bar.py',['a.txt','b.txt'])
96 >>> full_path('/foo/bar.py',['a.txt','b.txt'])
97 ['/foo/a.txt', '/foo/b.txt']
97 ['/foo/a.txt', '/foo/b.txt']
98
98
99 >>> full_path('/foo',['a.txt','b.txt'])
99 >>> full_path('/foo',['a.txt','b.txt'])
100 ['/a.txt', '/b.txt']
100 ['/a.txt', '/b.txt']
101
101
102 If a single file is given, the output is still a list:
102 If a single file is given, the output is still a list:
103 >>> full_path('/foo','a.txt')
103 >>> full_path('/foo','a.txt')
104 ['/a.txt']
104 ['/a.txt']
105 """
105 """
106
106
107 files = list_strings(files)
107 files = list_strings(files)
108 base = os.path.split(startPath)[0]
108 base = os.path.split(startPath)[0]
109 return [ os.path.join(base,f) for f in files ]
109 return [ os.path.join(base,f) for f in files ]
110
110
111
111
112 def parse_test_output(txt):
112 def parse_test_output(txt):
113 """Parse the output of a test run and return errors, failures.
113 """Parse the output of a test run and return errors, failures.
114
114
115 Parameters
115 Parameters
116 ----------
116 ----------
117 txt : str
117 txt : str
118 Text output of a test run, assumed to contain a line of one of the
118 Text output of a test run, assumed to contain a line of one of the
119 following forms::
119 following forms::
120 'FAILED (errors=1)'
120 'FAILED (errors=1)'
121 'FAILED (failures=1)'
121 'FAILED (failures=1)'
122 'FAILED (errors=1, failures=1)'
122 'FAILED (errors=1, failures=1)'
123
123
124 Returns
124 Returns
125 -------
125 -------
126 nerr, nfail: number of errors and failures.
126 nerr, nfail: number of errors and failures.
127 """
127 """
128
128
129 err_m = re.search(r'^FAILED \(errors=(\d+)\)', txt, re.MULTILINE)
129 err_m = re.search(r'^FAILED \(errors=(\d+)\)', txt, re.MULTILINE)
130 if err_m:
130 if err_m:
131 nerr = int(err_m.group(1))
131 nerr = int(err_m.group(1))
132 nfail = 0
132 nfail = 0
133 return nerr, nfail
133 return nerr, nfail
134
134
135 fail_m = re.search(r'^FAILED \(failures=(\d+)\)', txt, re.MULTILINE)
135 fail_m = re.search(r'^FAILED \(failures=(\d+)\)', txt, re.MULTILINE)
136 if fail_m:
136 if fail_m:
137 nerr = 0
137 nerr = 0
138 nfail = int(fail_m.group(1))
138 nfail = int(fail_m.group(1))
139 return nerr, nfail
139 return nerr, nfail
140
140
141 both_m = re.search(r'^FAILED \(errors=(\d+), failures=(\d+)\)', txt,
141 both_m = re.search(r'^FAILED \(errors=(\d+), failures=(\d+)\)', txt,
142 re.MULTILINE)
142 re.MULTILINE)
143 if both_m:
143 if both_m:
144 nerr = int(both_m.group(1))
144 nerr = int(both_m.group(1))
145 nfail = int(both_m.group(2))
145 nfail = int(both_m.group(2))
146 return nerr, nfail
146 return nerr, nfail
147
147
148 # If the input didn't match any of these forms, assume no error/failures
148 # If the input didn't match any of these forms, assume no error/failures
149 return 0, 0
149 return 0, 0
150
150
151
151
152 # So nose doesn't think this is a test
152 # So nose doesn't think this is a test
153 parse_test_output.__test__ = False
153 parse_test_output.__test__ = False
154
154
155
155
156 def default_argv():
156 def default_argv():
157 """Return a valid default argv for creating testing instances of ipython"""
157 """Return a valid default argv for creating testing instances of ipython"""
158
158
159 return ['--quick', # so no config file is loaded
159 return ['--quick', # so no config file is loaded
160 # Other defaults to minimize side effects on stdout
160 # Other defaults to minimize side effects on stdout
161 'colors=NoColor', '--no-term-title','--no-banner',
161 'colors=NoColor', '--no-term-title','--no-banner',
162 'autocall=0']
162 'autocall=0']
163
163
164
164
165 def default_config():
165 def default_config():
166 """Return a config object with good defaults for testing."""
166 """Return a config object with good defaults for testing."""
167 config = Config()
167 config = Config()
168 config.TerminalInteractiveShell.colors = 'NoColor'
168 config.TerminalInteractiveShell.colors = 'NoColor'
169 config.TerminalTerminalInteractiveShell.term_title = False,
169 config.TerminalTerminalInteractiveShell.term_title = False,
170 config.TerminalInteractiveShell.autocall = 0
170 config.TerminalInteractiveShell.autocall = 0
171 config.HistoryManager.hist_file = u'test_hist.sqlite'
171 config.HistoryManager.hist_file = u'test_hist.sqlite'
172 config.HistoryManager.db_cache_size = 10000
172 config.HistoryManager.db_cache_size = 10000
173 return config
173 return config
174
174
175
175
176 def ipexec(fname, options=None):
176 def ipexec(fname, options=None):
177 """Utility to call 'ipython filename'.
177 """Utility to call 'ipython filename'.
178
178
179 Starts IPython witha minimal and safe configuration to make startup as fast
179 Starts IPython witha minimal and safe configuration to make startup as fast
180 as possible.
180 as possible.
181
181
182 Note that this starts IPython in a subprocess!
182 Note that this starts IPython in a subprocess!
183
183
184 Parameters
184 Parameters
185 ----------
185 ----------
186 fname : str
186 fname : str
187 Name of file to be executed (should have .py or .ipy extension).
187 Name of file to be executed (should have .py or .ipy extension).
188
188
189 options : optional, list
189 options : optional, list
190 Extra command-line flags to be passed to IPython.
190 Extra command-line flags to be passed to IPython.
191
191
192 Returns
192 Returns
193 -------
193 -------
194 (stdout, stderr) of ipython subprocess.
194 (stdout, stderr) of ipython subprocess.
195 """
195 """
196 if options is None: options = []
196 if options is None: options = []
197
197
198 # For these subprocess calls, eliminate all prompt printing so we only see
198 # For these subprocess calls, eliminate all prompt printing so we only see
199 # output from script execution
199 # output from script execution
200 prompt_opts = ['pi1=""', 'pi2=""', 'po=""']
200 prompt_opts = [ 'InteractiveShell.prompt_in1=""',
201 'InteractiveShell.prompt_in2=""',
202 'InteractiveShell.prompt_out=""'
203 ]
201 cmdargs = ' '.join(default_argv() + prompt_opts + options)
204 cmdargs = ' '.join(default_argv() + prompt_opts + options)
202
205
203 _ip = get_ipython()
206 _ip = get_ipython()
204 test_dir = os.path.dirname(__file__)
207 test_dir = os.path.dirname(__file__)
205
208
206 ipython_cmd = find_cmd('ipython')
209 ipython_cmd = find_cmd('ipython')
207 # Absolute path for filename
210 # Absolute path for filename
208 full_fname = os.path.join(test_dir, fname)
211 full_fname = os.path.join(test_dir, fname)
209 full_cmd = '%s %s %s' % (ipython_cmd, cmdargs, full_fname)
212 full_cmd = '%s %s %s' % (ipython_cmd, cmdargs, full_fname)
210 #print >> sys.stderr, 'FULL CMD:', full_cmd # dbg
213 #print >> sys.stderr, 'FULL CMD:', full_cmd # dbg
211 return getoutputerror(full_cmd)
214 return getoutputerror(full_cmd)
212
215
213
216
214 def ipexec_validate(fname, expected_out, expected_err='',
217 def ipexec_validate(fname, expected_out, expected_err='',
215 options=None):
218 options=None):
216 """Utility to call 'ipython filename' and validate output/error.
219 """Utility to call 'ipython filename' and validate output/error.
217
220
218 This function raises an AssertionError if the validation fails.
221 This function raises an AssertionError if the validation fails.
219
222
220 Note that this starts IPython in a subprocess!
223 Note that this starts IPython in a subprocess!
221
224
222 Parameters
225 Parameters
223 ----------
226 ----------
224 fname : str
227 fname : str
225 Name of the file to be executed (should have .py or .ipy extension).
228 Name of the file to be executed (should have .py or .ipy extension).
226
229
227 expected_out : str
230 expected_out : str
228 Expected stdout of the process.
231 Expected stdout of the process.
229
232
230 expected_err : optional, str
233 expected_err : optional, str
231 Expected stderr of the process.
234 Expected stderr of the process.
232
235
233 options : optional, list
236 options : optional, list
234 Extra command-line flags to be passed to IPython.
237 Extra command-line flags to be passed to IPython.
235
238
236 Returns
239 Returns
237 -------
240 -------
238 None
241 None
239 """
242 """
240
243
241 import nose.tools as nt
244 import nose.tools as nt
242
245
243 out, err = ipexec(fname)
246 out, err = ipexec(fname)
244 #print 'OUT', out # dbg
247 #print 'OUT', out # dbg
245 #print 'ERR', err # dbg
248 #print 'ERR', err # dbg
246 # If there are any errors, we must check those befor stdout, as they may be
249 # If there are any errors, we must check those befor stdout, as they may be
247 # more informative than simply having an empty stdout.
250 # more informative than simply having an empty stdout.
248 if err:
251 if err:
249 if expected_err:
252 if expected_err:
250 nt.assert_equals(err.strip(), expected_err.strip())
253 nt.assert_equals(err.strip(), expected_err.strip())
251 else:
254 else:
252 raise ValueError('Running file %r produced error: %r' %
255 raise ValueError('Running file %r produced error: %r' %
253 (fname, err))
256 (fname, err))
254 # If no errors or output on stderr was expected, match stdout
257 # If no errors or output on stderr was expected, match stdout
255 nt.assert_equals(out.strip(), expected_out.strip())
258 nt.assert_equals(out.strip(), expected_out.strip())
256
259
257
260
258 class TempFileMixin(object):
261 class TempFileMixin(object):
259 """Utility class to create temporary Python/IPython files.
262 """Utility class to create temporary Python/IPython files.
260
263
261 Meant as a mixin class for test cases."""
264 Meant as a mixin class for test cases."""
262
265
263 def mktmp(self, src, ext='.py'):
266 def mktmp(self, src, ext='.py'):
264 """Make a valid python temp file."""
267 """Make a valid python temp file."""
265 fname, f = temp_pyfile(src, ext)
268 fname, f = temp_pyfile(src, ext)
266 self.tmpfile = f
269 self.tmpfile = f
267 self.fname = fname
270 self.fname = fname
268
271
269 def tearDown(self):
272 def tearDown(self):
270 if hasattr(self, 'tmpfile'):
273 if hasattr(self, 'tmpfile'):
271 # If the tmpfile wasn't made because of skipped tests, like in
274 # If the tmpfile wasn't made because of skipped tests, like in
272 # win32, there's nothing to cleanup.
275 # win32, there's nothing to cleanup.
273 self.tmpfile.close()
276 self.tmpfile.close()
274 try:
277 try:
275 os.unlink(self.fname)
278 os.unlink(self.fname)
276 except:
279 except:
277 # On Windows, even though we close the file, we still can't
280 # On Windows, even though we close the file, we still can't
278 # delete it. I have no clue why
281 # delete it. I have no clue why
279 pass
282 pass
280
283
General Comments 0
You need to be logged in to leave comments. Login now