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