Format: text/x-python
⬇ Download File (3.9 KB)
   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