##// END OF EJS Templates
Partly revert "remove now-obsolete use of skip_doctest outside core"...
Nikita Kniazev -
Show More
@@ -1,164 +1,168 b''
1 """Tests for the decorators we've created for IPython.
1 """Tests for the decorators we've created for IPython.
2 """
2 """
3
3
4 # Module imports
4 # Module imports
5 # Std lib
5 # Std lib
6 import inspect
6 import inspect
7 import sys
7 import sys
8
8
9 # Third party
9 # Third party
10 import nose.tools as nt
10 import nose.tools as nt
11
11
12 # Our own
12 # Our own
13 from IPython.testing import decorators as dec
13 from IPython.testing import decorators as dec
14 from IPython.testing.skipdoctest import skip_doctest
14
15
15 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
16 # Utilities
17 # Utilities
17
18
18 # Note: copied from OInspect, kept here so the testing stuff doesn't create
19 # Note: copied from OInspect, kept here so the testing stuff doesn't create
19 # circular dependencies and is easier to reuse.
20 # circular dependencies and is easier to reuse.
20 def getargspec(obj):
21 def getargspec(obj):
21 """Get the names and default values of a function's arguments.
22 """Get the names and default values of a function's arguments.
22
23
23 A tuple of four things is returned: (args, varargs, varkw, defaults).
24 A tuple of four things is returned: (args, varargs, varkw, defaults).
24 'args' is a list of the argument names (it may contain nested lists).
25 'args' is a list of the argument names (it may contain nested lists).
25 'varargs' and 'varkw' are the names of the * and ** arguments or None.
26 'varargs' and 'varkw' are the names of the * and ** arguments or None.
26 'defaults' is an n-tuple of the default values of the last n arguments.
27 'defaults' is an n-tuple of the default values of the last n arguments.
27
28
28 Modified version of inspect.getargspec from the Python Standard
29 Modified version of inspect.getargspec from the Python Standard
29 Library."""
30 Library."""
30
31
31 if inspect.isfunction(obj):
32 if inspect.isfunction(obj):
32 func_obj = obj
33 func_obj = obj
33 elif inspect.ismethod(obj):
34 elif inspect.ismethod(obj):
34 func_obj = obj.__func__
35 func_obj = obj.__func__
35 else:
36 else:
36 raise TypeError('arg is not a Python function')
37 raise TypeError('arg is not a Python function')
37 args, varargs, varkw = inspect.getargs(func_obj.__code__)
38 args, varargs, varkw = inspect.getargs(func_obj.__code__)
38 return args, varargs, varkw, func_obj.__defaults__
39 return args, varargs, varkw, func_obj.__defaults__
39
40
40 #-----------------------------------------------------------------------------
41 #-----------------------------------------------------------------------------
41 # Testing functions
42 # Testing functions
42
43
43 @dec.as_unittest
44 @dec.as_unittest
44 def trivial():
45 def trivial():
45 """A trivial test"""
46 """A trivial test"""
46 pass
47 pass
47
48
48
49
49 @dec.skip()
50 @dec.skip()
50 def test_deliberately_broken():
51 def test_deliberately_broken():
51 """A deliberately broken test - we want to skip this one."""
52 """A deliberately broken test - we want to skip this one."""
52 1/0
53 1/0
53
54
54 @dec.skip('Testing the skip decorator')
55 @dec.skip('Testing the skip decorator')
55 def test_deliberately_broken2():
56 def test_deliberately_broken2():
56 """Another deliberately broken test - we want to skip this one."""
57 """Another deliberately broken test - we want to skip this one."""
57 1/0
58 1/0
58
59
59
60
60 # Verify that we can correctly skip the doctest for a function at will, but
61 # Verify that we can correctly skip the doctest for a function at will, but
61 # that the docstring itself is NOT destroyed by the decorator.
62 # that the docstring itself is NOT destroyed by the decorator.
63 @skip_doctest
62 def doctest_bad(x,y=1,**k):
64 def doctest_bad(x,y=1,**k):
63 """A function whose doctest we need to skip.
65 """A function whose doctest we need to skip.
64
66
65 >>> 1+1
67 >>> 1+1
66 3
68 3
67 """
69 """
68 print('x:',x)
70 print('x:',x)
69 print('y:',y)
71 print('y:',y)
70 print('k:',k)
72 print('k:',k)
71
73
72
74
73 def call_doctest_bad():
75 def call_doctest_bad():
74 """Check that we can still call the decorated functions.
76 """Check that we can still call the decorated functions.
75
77
76 >>> doctest_bad(3,y=4)
78 >>> doctest_bad(3,y=4)
77 x: 3
79 x: 3
78 y: 4
80 y: 4
79 k: {}
81 k: {}
80 """
82 """
81 pass
83 pass
82
84
83
85
84 def test_skip_dt_decorator():
86 def test_skip_dt_decorator():
85 """Doctest-skipping decorator should preserve the docstring.
87 """Doctest-skipping decorator should preserve the docstring.
86 """
88 """
87 # Careful: 'check' must be a *verbatim* copy of the doctest_bad docstring!
89 # Careful: 'check' must be a *verbatim* copy of the doctest_bad docstring!
88 check = """A function whose doctest we need to skip.
90 check = """A function whose doctest we need to skip.
89
91
90 >>> 1+1
92 >>> 1+1
91 3
93 3
92 """
94 """
93 # Fetch the docstring from doctest_bad after decoration.
95 # Fetch the docstring from doctest_bad after decoration.
94 val = doctest_bad.__doc__
96 val = doctest_bad.__doc__
95
97
96 nt.assert_equal(check,val,"doctest_bad docstrings don't match")
98 nt.assert_equal(check,val,"doctest_bad docstrings don't match")
97
99
98
100
99 # Doctest skipping should work for class methods too
101 # Doctest skipping should work for class methods too
100 class FooClass(object):
102 class FooClass(object):
101 """FooClass
103 """FooClass
102
104
103 Example:
105 Example:
104
106
105 >>> 1+1
107 >>> 1+1
106 2
108 2
107 """
109 """
108
110
111 @skip_doctest
109 def __init__(self,x):
112 def __init__(self,x):
110 """Make a FooClass.
113 """Make a FooClass.
111
114
112 Example:
115 Example:
113
116
114 >>> f = FooClass(3)
117 >>> f = FooClass(3)
115 junk
118 junk
116 """
119 """
117 print('Making a FooClass.')
120 print('Making a FooClass.')
118 self.x = x
121 self.x = x
119
122
123 @skip_doctest
120 def bar(self,y):
124 def bar(self,y):
121 """Example:
125 """Example:
122
126
123 >>> ff = FooClass(3)
127 >>> ff = FooClass(3)
124 >>> ff.bar(0)
128 >>> ff.bar(0)
125 boom!
129 boom!
126 >>> 1/0
130 >>> 1/0
127 bam!
131 bam!
128 """
132 """
129 return 1/y
133 return 1/y
130
134
131 def baz(self,y):
135 def baz(self,y):
132 """Example:
136 """Example:
133
137
134 >>> ff2 = FooClass(3)
138 >>> ff2 = FooClass(3)
135 Making a FooClass.
139 Making a FooClass.
136 >>> ff2.baz(3)
140 >>> ff2.baz(3)
137 True
141 True
138 """
142 """
139 return self.x==y
143 return self.x==y
140
144
141
145
142 def test_skip_dt_decorator2():
146 def test_skip_dt_decorator2():
143 """Doctest-skipping decorator should preserve function signature.
147 """Doctest-skipping decorator should preserve function signature.
144 """
148 """
145 # Hardcoded correct answer
149 # Hardcoded correct answer
146 dtargs = (['x', 'y'], None, 'k', (1,))
150 dtargs = (['x', 'y'], None, 'k', (1,))
147 # Introspect out the value
151 # Introspect out the value
148 dtargsr = getargspec(doctest_bad)
152 dtargsr = getargspec(doctest_bad)
149 assert dtargsr==dtargs, \
153 assert dtargsr==dtargs, \
150 "Incorrectly reconstructed args for doctest_bad: %s" % (dtargsr,)
154 "Incorrectly reconstructed args for doctest_bad: %s" % (dtargsr,)
151
155
152
156
153 @dec.skip_linux
157 @dec.skip_linux
154 def test_linux():
158 def test_linux():
155 nt.assert_false(sys.platform.startswith('linux'),"This test can't run under linux")
159 nt.assert_false(sys.platform.startswith('linux'),"This test can't run under linux")
156
160
157 @dec.skip_win32
161 @dec.skip_win32
158 def test_win32():
162 def test_win32():
159 nt.assert_not_equal(sys.platform,'win32',"This test can't run under windows")
163 nt.assert_not_equal(sys.platform,'win32',"This test can't run under windows")
160
164
161 @dec.skip_osx
165 @dec.skip_osx
162 def test_osx():
166 def test_osx():
163 nt.assert_not_equal(sys.platform,'darwin',"This test can't run under osx")
167 nt.assert_not_equal(sys.platform,'darwin',"This test can't run under osx")
164
168
General Comments 0
You need to be logged in to leave comments. Login now