##// END OF EJS Templates
Add new decorators to skip os-specific tests....
Fernando Perez -
Show More
@@ -0,0 +1,161 b''
1 """Tests for the decorators we've created for IPython.
2 """
3
4 # Module imports
5 # Std lib
6 import inspect
7 import sys
8
9 # Third party
10 import nose.tools as nt
11
12 # Our own
13 from IPython.testing import decorators as dec
14
15
16 #-----------------------------------------------------------------------------
17 # Utilities
18
19 # Note: copied from OInspect, kept here so the testing stuff doesn't create
20 # circular dependencies and is easier to reuse.
21 def getargspec(obj):
22 """Get the names and default values of a function's arguments.
23
24 A tuple of four things is returned: (args, varargs, varkw, defaults).
25 'args' is a list of the argument names (it may contain nested lists).
26 'varargs' and 'varkw' are the names of the * and ** arguments or None.
27 'defaults' is an n-tuple of the default values of the last n arguments.
28
29 Modified version of inspect.getargspec from the Python Standard
30 Library."""
31
32 if inspect.isfunction(obj):
33 func_obj = obj
34 elif inspect.ismethod(obj):
35 func_obj = obj.im_func
36 else:
37 raise TypeError, 'arg is not a Python function'
38 args, varargs, varkw = inspect.getargs(func_obj.func_code)
39 return args, varargs, varkw, func_obj.func_defaults
40
41 #-----------------------------------------------------------------------------
42 # Testing functions
43
44 @dec.skip
45 def test_deliberately_broken():
46 """A deliberately broken test - we want to skip this one."""
47 1/0
48
49 @dec.skip('foo')
50 def test_deliberately_broken2():
51 """Another deliberately broken test - we want to skip this one."""
52 1/0
53
54
55 # Verify that we can correctly skip the doctest for a function at will, but
56 # that the docstring itself is NOT destroyed by the decorator.
57 @dec.skip_doctest
58 def doctest_bad(x,y=1,**k):
59 """A function whose doctest we need to skip.
60
61 >>> 1+1
62 3
63 """
64 print 'x:',x
65 print 'y:',y
66 print 'k:',k
67
68
69 def call_doctest_bad():
70 """Check that we can still call the decorated functions.
71
72 >>> doctest_bad(3,y=4)
73 x: 3
74 y: 4
75 k: {}
76 """
77 pass
78
79
80 def test_skip_dt_decorator():
81 """Doctest-skipping decorator should preserve the docstring.
82 """
83 # Careful: 'check' must be a *verbatim* copy of the doctest_bad docstring!
84 check = """A function whose doctest we need to skip.
85
86 >>> 1+1
87 3
88 """
89 # Fetch the docstring from doctest_bad after decoration.
90 val = doctest_bad.__doc__
91
92 assert check==val,"doctest_bad docstrings don't match"
93
94 # Doctest skipping should work for class methods too
95 class foo(object):
96 """Foo
97
98 Example:
99
100 >>> 1+1
101 2
102 """
103
104 @dec.skip_doctest
105 def __init__(self,x):
106 """Make a foo.
107
108 Example:
109
110 >>> f = foo(3)
111 junk
112 """
113 print 'Making a foo.'
114 self.x = x
115
116 @dec.skip_doctest
117 def bar(self,y):
118 """Example:
119
120 >>> f = foo(3)
121 >>> f.bar(0)
122 boom!
123 >>> 1/0
124 bam!
125 """
126 return 1/y
127
128 def baz(self,y):
129 """Example:
130
131 >>> f = foo(3)
132 Making a foo.
133 >>> f.baz(3)
134 True
135 """
136 return self.x==y
137
138
139
140 def test_skip_dt_decorator2():
141 """Doctest-skipping decorator should preserve function signature.
142 """
143 # Hardcoded correct answer
144 dtargs = (['x', 'y'], None, 'k', (1,))
145 # Introspect out the value
146 dtargsr = getargspec(doctest_bad)
147 assert dtargsr==dtargs, \
148 "Incorrectly reconstructed args for doctest_bad: %s" % (dtargsr,)
149
150
151 @dec.skip_linux
152 def test_linux():
153 nt.assert_not_equals(sys.platform,'linux2',"This test can't run under linux")
154
155 @dec.skip_win32
156 def test_win32():
157 nt.assert_not_equals(sys.platform,'win32',"This test can't run under windows")
158
159 @dec.skip_osx
160 def test_osx():
161 nt.assert_not_equals(sys.platform,'darwin',"This test can't run under osx")
@@ -1,68 +1,70 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 Test the output capture at the OS level, using file descriptors.
3 Test the output capture at the OS level, using file descriptors.
4 """
4 """
5
5
6 __docformat__ = "restructuredtext en"
6 __docformat__ = "restructuredtext en"
7
7
8 #-------------------------------------------------------------------------------
8 #-------------------------------------------------------------------------------
9 # Copyright (C) 2008 The IPython Development Team
9 # Copyright (C) 2008 The IPython Development Team
10 #
10 #
11 # Distributed under the terms of the BSD License. The full license is
11 # Distributed under the terms of the BSD License. The full license is
12 # in the file COPYING, distributed as part of this software.
12 # in the file COPYING, distributed as part of this software.
13 #-------------------------------------------------------------------------------
13 #-------------------------------------------------------------------------------
14
14
15
15
16 # Stdlib imports
16 import os
17 import os
17 from cStringIO import StringIO
18 from cStringIO import StringIO
18
19
19 # FIXME:
20 # Our own imports
20 import nose
21 from IPython.testing import decorators as dec
21 import sys
22 if sys.platform == 'win32':
23 raise nose.SkipTest("These tests are not reliable under windows")
24
22
23 #-----------------------------------------------------------------------------
24 # Test functions
25
26 @dec.skip_win32
25 def test_redirector():
27 def test_redirector():
26 """ Checks that the redirector can be used to do synchronous capture.
28 """ Checks that the redirector can be used to do synchronous capture.
27 """
29 """
28 from IPython.kernel.core.fd_redirector import FDRedirector
30 from IPython.kernel.core.fd_redirector import FDRedirector
29 r = FDRedirector()
31 r = FDRedirector()
30 out = StringIO()
32 out = StringIO()
31 try:
33 try:
32 r.start()
34 r.start()
33 for i in range(10):
35 for i in range(10):
34 os.system('echo %ic' % i)
36 os.system('echo %ic' % i)
35 print >>out, r.getvalue(),
37 print >>out, r.getvalue(),
36 print >>out, i
38 print >>out, i
37 except:
39 except:
38 r.stop()
40 r.stop()
39 raise
41 raise
40 r.stop()
42 r.stop()
41 result1 = out.getvalue()
43 result1 = out.getvalue()
42 result2 = "".join("%ic\n%i\n" %(i, i) for i in range(10))
44 result2 = "".join("%ic\n%i\n" %(i, i) for i in range(10))
43 assert result1 == result2
45 assert result1 == result2
44
46
47
48 @dec.skip_win32
45 def test_redirector_output_trap():
49 def test_redirector_output_trap():
46 """ This test check not only that the redirector_output_trap does
50 """ This test check not only that the redirector_output_trap does
47 trap the output, but also that it does it in a gready way, that
51 trap the output, but also that it does it in a gready way, that
48 is by calling the callback ASAP.
52 is by calling the callback ASAP.
49 """
53 """
50 from IPython.kernel.core.redirector_output_trap import RedirectorOutputTrap
54 from IPython.kernel.core.redirector_output_trap import RedirectorOutputTrap
51 out = StringIO()
55 out = StringIO()
52 trap = RedirectorOutputTrap(out.write, out.write)
56 trap = RedirectorOutputTrap(out.write, out.write)
53 try:
57 try:
54 trap.set()
58 trap.set()
55 for i in range(10):
59 for i in range(10):
56 os.system('echo %ic' % i)
60 os.system('echo %ic' % i)
57 print "%ip" % i
61 print "%ip" % i
58 print >>out, i
62 print >>out, i
59 except:
63 except:
60 trap.unset()
64 trap.unset()
61 raise
65 raise
62 trap.unset()
66 trap.unset()
63 result1 = out.getvalue()
67 result1 = out.getvalue()
64 result2 = "".join("%ic\n%ip\n%i\n" %(i, i, i) for i in range(10))
68 result2 = "".join("%ic\n%ip\n%i\n" %(i, i, i) for i in range(10))
65 assert result1 == result2
69 assert result1 == result2
66
67
70
68
@@ -1,147 +1,160 b''
1 """Decorators for labeling test objects.
1 """Decorators for labeling test objects.
2
2
3 Decorators that merely return a modified version of the original
3 Decorators that merely return a modified version of the original
4 function object are straightforward. Decorators that return a new
4 function object are straightforward. Decorators that return a new
5 function object need to use
5 function object need to use
6 nose.tools.make_decorator(original_function)(decorator) in returning
6 nose.tools.make_decorator(original_function)(decorator) in returning
7 the decorator, in order to preserve metadata such as function name,
7 the decorator, in order to preserve metadata such as function name,
8 setup and teardown functions and so on - see nose.tools for more
8 setup and teardown functions and so on - see nose.tools for more
9 information.
9 information.
10
10
11 This module provides a set of useful decorators meant to be ready to use in
12 your own tests. See the bottom of the file for the ready-made ones, and if you
13 find yourself writing a new one that may be of generic use, add it here.
14
11 NOTE: This file contains IPython-specific decorators and imports the
15 NOTE: This file contains IPython-specific decorators and imports the
12 numpy.testing.decorators file, which we've copied verbatim. Any of our own
16 numpy.testing.decorators file, which we've copied verbatim. Any of our own
13 code will be added at the bottom if we end up extending this.
17 code will be added at the bottom if we end up extending this.
14 """
18 """
15
19
16 # Stdlib imports
20 # Stdlib imports
17 import inspect
21 import inspect
22 import sys
18
23
19 # Third-party imports
24 # Third-party imports
20
25
21 # This is Michele Simionato's decorator module, also kept verbatim.
26 # This is Michele Simionato's decorator module, also kept verbatim.
22 from decorator_msim import decorator, update_wrapper
27 from decorator_msim import decorator, update_wrapper
23
28
24 # Grab the numpy-specific decorators which we keep in a file that we
29 # Grab the numpy-specific decorators which we keep in a file that we
25 # occasionally update from upstream: decorators_numpy.py is an IDENTICAL copy
30 # occasionally update from upstream: decorators_numpy.py is an IDENTICAL copy
26 # of numpy.testing.decorators.
31 # of numpy.testing.decorators.
27 from decorators_numpy import *
32 from decorators_numpy import *
28
33
29 ##############################################################################
34 ##############################################################################
30 # Local code begins
35 # Local code begins
31
36
32 # Utility functions
37 # Utility functions
33
38
34 def apply_wrapper(wrapper,func):
39 def apply_wrapper(wrapper,func):
35 """Apply a wrapper to a function for decoration.
40 """Apply a wrapper to a function for decoration.
36
41
37 This mixes Michele Simionato's decorator tool with nose's make_decorator,
42 This mixes Michele Simionato's decorator tool with nose's make_decorator,
38 to apply a wrapper in a decorator so that all nose attributes, as well as
43 to apply a wrapper in a decorator so that all nose attributes, as well as
39 function signature and other properties, survive the decoration cleanly.
44 function signature and other properties, survive the decoration cleanly.
40 This will ensure that wrapped functions can still be well introspected via
45 This will ensure that wrapped functions can still be well introspected via
41 IPython, for example.
46 IPython, for example.
42 """
47 """
43 import nose.tools
48 import nose.tools
44
49
45 return decorator(wrapper,nose.tools.make_decorator(func)(wrapper))
50 return decorator(wrapper,nose.tools.make_decorator(func)(wrapper))
46
51
47
52
48 def make_label_dec(label,ds=None):
53 def make_label_dec(label,ds=None):
49 """Factory function to create a decorator that applies one or more labels.
54 """Factory function to create a decorator that applies one or more labels.
50
55
51 :Parameters:
56 :Parameters:
52 label : string or sequence
57 label : string or sequence
53 One or more labels that will be applied by the decorator to the functions
58 One or more labels that will be applied by the decorator to the functions
54 it decorates. Labels are attributes of the decorated function with their
59 it decorates. Labels are attributes of the decorated function with their
55 value set to True.
60 value set to True.
56
61
57 :Keywords:
62 :Keywords:
58 ds : string
63 ds : string
59 An optional docstring for the resulting decorator. If not given, a
64 An optional docstring for the resulting decorator. If not given, a
60 default docstring is auto-generated.
65 default docstring is auto-generated.
61
66
62 :Returns:
67 :Returns:
63 A decorator.
68 A decorator.
64
69
65 :Examples:
70 :Examples:
66
71
67 A simple labeling decorator:
72 A simple labeling decorator:
68 >>> slow = make_label_dec('slow')
73 >>> slow = make_label_dec('slow')
69 >>> print slow.__doc__
74 >>> print slow.__doc__
70 Labels a test as 'slow'.
75 Labels a test as 'slow'.
71
76
72 And one that uses multiple labels and a custom docstring:
77 And one that uses multiple labels and a custom docstring:
73 >>> rare = make_label_dec(['slow','hard'],
78 >>> rare = make_label_dec(['slow','hard'],
74 ... "Mix labels 'slow' and 'hard' for rare tests.")
79 ... "Mix labels 'slow' and 'hard' for rare tests.")
75 >>> print rare.__doc__
80 >>> print rare.__doc__
76 Mix labels 'slow' and 'hard' for rare tests.
81 Mix labels 'slow' and 'hard' for rare tests.
77
82
78 Now, let's test using this one:
83 Now, let's test using this one:
79 >>> @rare
84 >>> @rare
80 ... def f(): pass
85 ... def f(): pass
81 ...
86 ...
82 >>>
87 >>>
83 >>> f.slow
88 >>> f.slow
84 True
89 True
85 >>> f.hard
90 >>> f.hard
86 True
91 True
87 """
92 """
88
93
89 if isinstance(label,basestring):
94 if isinstance(label,basestring):
90 labels = [label]
95 labels = [label]
91 else:
96 else:
92 labels = label
97 labels = label
93
98
94 # Validate that the given label(s) are OK for use in setattr() by doing a
99 # Validate that the given label(s) are OK for use in setattr() by doing a
95 # dry run on a dummy function.
100 # dry run on a dummy function.
96 tmp = lambda : None
101 tmp = lambda : None
97 for label in labels:
102 for label in labels:
98 setattr(tmp,label,True)
103 setattr(tmp,label,True)
99
104
100 # This is the actual decorator we'll return
105 # This is the actual decorator we'll return
101 def decor(f):
106 def decor(f):
102 for label in labels:
107 for label in labels:
103 setattr(f,label,True)
108 setattr(f,label,True)
104 return f
109 return f
105
110
106 # Apply the user's docstring, or autogenerate a basic one
111 # Apply the user's docstring, or autogenerate a basic one
107 if ds is None:
112 if ds is None:
108 ds = "Labels a test as %r." % label
113 ds = "Labels a test as %r." % label
109 decor.__doc__ = ds
114 decor.__doc__ = ds
110
115
111 return decor
116 return decor
112
117
113 #-----------------------------------------------------------------------------
118 #-----------------------------------------------------------------------------
114 # Decorators for public use
119 # Decorators for public use
115
120
116 skip_doctest = make_label_dec('skip_doctest',
121 skip_doctest = make_label_dec('skip_doctest',
117 """Decorator - mark a function or method for skipping its doctest.
122 """Decorator - mark a function or method for skipping its doctest.
118
123
119 This decorator allows you to mark a function whose docstring you wish to
124 This decorator allows you to mark a function whose docstring you wish to
120 omit from testing, while preserving the docstring for introspection, help,
125 omit from testing, while preserving the docstring for introspection, help,
121 etc.""")
126 etc.""")
122
127
123 def skip(msg=''):
128 def skip(msg=''):
124 """Decorator - mark a test function for skipping from test suite.
129 """Decorator - mark a test function for skipping from test suite.
125
130
131 This function *is* already a decorator, it is not a factory like
132 make_label_dec or some of those in decorators_numpy.
133
126 :Parameters:
134 :Parameters:
127
135
128 func : function
136 func : function
129 Test function to be skipped
137 Test function to be skipped
130
138
131 msg : string
139 msg : string
132 Optional message to be added.
140 Optional message to be added.
133 """
141 """
134
142
135 import nose
143 import nose
136
144
137 def inner(func):
145 def inner(func):
138
146
139 def wrapper(*a,**k):
147 def wrapper(*a,**k):
140 if msg: out = '\n'+msg
148 if msg: out = '\n'+msg
141 else: out = ''
149 else: out = ''
142 raise nose.SkipTest("Skipping test for function: %s%s" %
150 raise nose.SkipTest("Skipping test for function: %s%s" %
143 (func.__name__,out))
151 (func.__name__,out))
144
152
145 return apply_wrapper(wrapper,func)
153 return apply_wrapper(wrapper,func)
146
154
147 return inner
155 return inner
156
157 # Decorators to skip certain tests on specific platforms.
158 skip_win32 = skipif(sys.platform=='win32',"This test does not run under Windows")
159 skip_linux = skipif(sys.platform=='linux2',"This test does not run under Linux")
160 skip_osx = skipif(sys.platform=='darwin',"This test does not run under OSX")
@@ -1,185 +1,51 b''
1 """Some simple tests for the plugin while running scripts.
2 """
1 # Module imports
3 # Module imports
2 # Std lib
4 # Std lib
3 import inspect
5 import inspect
4
6
5 # Third party
6
7 # Our own
7 # Our own
8 from IPython.testing import decorators as dec
8 from IPython.testing import decorators as dec
9
9
10 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
11 # Utilities
12
13 # Note: copied from OInspect, kept here so the testing stuff doesn't create
14 # circular dependencies and is easier to reuse.
15 def getargspec(obj):
16 """Get the names and default values of a function's arguments.
17
18 A tuple of four things is returned: (args, varargs, varkw, defaults).
19 'args' is a list of the argument names (it may contain nested lists).
20 'varargs' and 'varkw' are the names of the * and ** arguments or None.
21 'defaults' is an n-tuple of the default values of the last n arguments.
22
23 Modified version of inspect.getargspec from the Python Standard
24 Library."""
25
26 if inspect.isfunction(obj):
27 func_obj = obj
28 elif inspect.ismethod(obj):
29 func_obj = obj.im_func
30 else:
31 raise TypeError, 'arg is not a Python function'
32 args, varargs, varkw = inspect.getargs(func_obj.func_code)
33 return args, varargs, varkw, func_obj.func_defaults
34
35 #-----------------------------------------------------------------------------
36 # Testing functions
11 # Testing functions
37
12
38 def test_trivial():
13 def test_trivial():
39 """A trivial passing test."""
14 """A trivial passing test."""
40 pass
15 pass
41
16
42
43 @dec.skip
44 def test_deliberately_broken():
45 """A deliberately broken test - we want to skip this one."""
46 1/0
47
48 @dec.skip('foo')
49 def test_deliberately_broken2():
50 """Another deliberately broken test - we want to skip this one."""
51 1/0
52
53
54 # Verify that we can correctly skip the doctest for a function at will, but
55 # that the docstring itself is NOT destroyed by the decorator.
56 @dec.skip_doctest
57 def doctest_bad(x,y=1,**k):
58 """A function whose doctest we need to skip.
59
60 >>> 1+1
61 3
62 """
63 print 'x:',x
64 print 'y:',y
65 print 'k:',k
66
67
68 def call_doctest_bad():
69 """Check that we can still call the decorated functions.
70
71 >>> doctest_bad(3,y=4)
72 x: 3
73 y: 4
74 k: {}
75 """
76 pass
77
78
79 # Doctest skipping should work for class methods too
80 class foo(object):
81 """Foo
82
83 Example:
84
85 >>> 1+1
86 2
87 """
88
89 @dec.skip_doctest
90 def __init__(self,x):
91 """Make a foo.
92
93 Example:
94
95 >>> f = foo(3)
96 junk
97 """
98 print 'Making a foo.'
99 self.x = x
100
101 @dec.skip_doctest
102 def bar(self,y):
103 """Example:
104
105 >>> f = foo(3)
106 >>> f.bar(0)
107 boom!
108 >>> 1/0
109 bam!
110 """
111 return 1/y
112
113 def baz(self,y):
114 """Example:
115
116 >>> f = foo(3)
117 Making a foo.
118 >>> f.baz(3)
119 True
120 """
121 return self.x==y
122
123
124 def test_skip_dt_decorator():
125 """Doctest-skipping decorator should preserve the docstring.
126 """
127 # Careful: 'check' must be a *verbatim* copy of the doctest_bad docstring!
128 check = """A function whose doctest we need to skip.
129
130 >>> 1+1
131 3
132 """
133 # Fetch the docstring from doctest_bad after decoration.
134 val = doctest_bad.__doc__
135
136 assert check==val,"doctest_bad docstrings don't match"
137
138
139 def test_skip_dt_decorator2():
140 """Doctest-skipping decorator should preserve function signature.
141 """
142 # Hardcoded correct answer
143 dtargs = (['x', 'y'], None, 'k', (1,))
144 # Introspect out the value
145 dtargsr = getargspec(doctest_bad)
146 assert dtargsr==dtargs, \
147 "Incorrectly reconstructed args for doctest_bad: %s" % (dtargsr,)
148
149
150 def doctest_run():
17 def doctest_run():
151 """Test running a trivial script.
18 """Test running a trivial script.
152
19
153 In [13]: run simplevars.py
20 In [13]: run simplevars.py
154 x is: 1
21 x is: 1
155 """
22 """
156
23
157 #@dec.skip_doctest
158 def doctest_runvars():
24 def doctest_runvars():
159 """Test that variables defined in scripts get loaded correcly via %run.
25 """Test that variables defined in scripts get loaded correcly via %run.
160
26
161 In [13]: run simplevars.py
27 In [13]: run simplevars.py
162 x is: 1
28 x is: 1
163
29
164 In [14]: x
30 In [14]: x
165 Out[14]: 1
31 Out[14]: 1
166 """
32 """
167
33
168 def doctest_ivars():
34 def doctest_ivars():
169 """Test that variables defined interactively are picked up.
35 """Test that variables defined interactively are picked up.
170 In [5]: zz=1
36 In [5]: zz=1
171
37
172 In [6]: zz
38 In [6]: zz
173 Out[6]: 1
39 Out[6]: 1
174 """
40 """
175
41
176 @dec.skip_doctest
42 @dec.skip_doctest
177 def doctest_refs():
43 def doctest_refs():
178 """DocTest reference holding issues when running scripts.
44 """DocTest reference holding issues when running scripts.
179
45
180 In [32]: run show_refs.py
46 In [32]: run show_refs.py
181 c referrers: [<type 'dict'>]
47 c referrers: [<type 'dict'>]
182
48
183 In [33]: map(type,gc.get_referrers(c))
49 In [33]: map(type,gc.get_referrers(c))
184 Out[33]: [<type 'dict'>]
50 Out[33]: [<type 'dict'>]
185 """
51 """
General Comments 0
You need to be logged in to leave comments. Login now