From 1d6f14c15dab5f2b03a4d07effdc3c9453a8ea6a 2008-09-15 02:07:52 From: Fernando Perez Date: 2008-09-15 02:07:52 Subject: [PATCH] Add new decorators to skip os-specific tests. Applied these to some tests we need to skip on win32, other misc. testing cleanup. --- diff --git a/IPython/kernel/core/tests/test_redirectors.py b/IPython/kernel/core/tests/test_redirectors.py index 27b638d..81aa0ba 100644 --- a/IPython/kernel/core/tests/test_redirectors.py +++ b/IPython/kernel/core/tests/test_redirectors.py @@ -13,15 +13,17 @@ __docformat__ = "restructuredtext en" #------------------------------------------------------------------------------- +# Stdlib imports import os from cStringIO import StringIO -# FIXME: -import nose -import sys -if sys.platform == 'win32': - raise nose.SkipTest("These tests are not reliable under windows") +# Our own imports +from IPython.testing import decorators as dec +#----------------------------------------------------------------------------- +# Test functions + +@dec.skip_win32 def test_redirector(): """ Checks that the redirector can be used to do synchronous capture. """ @@ -42,6 +44,8 @@ def test_redirector(): result2 = "".join("%ic\n%i\n" %(i, i) for i in range(10)) assert result1 == result2 + +@dec.skip_win32 def test_redirector_output_trap(): """ This test check not only that the redirector_output_trap does trap the output, but also that it does it in a gready way, that @@ -63,6 +67,4 @@ def test_redirector_output_trap(): result1 = out.getvalue() result2 = "".join("%ic\n%ip\n%i\n" %(i, i, i) for i in range(10)) assert result1 == result2 - - diff --git a/IPython/testing/decorators.py b/IPython/testing/decorators.py index 78b6840..6cbe0a7 100644 --- a/IPython/testing/decorators.py +++ b/IPython/testing/decorators.py @@ -8,6 +8,10 @@ the decorator, in order to preserve metadata such as function name, setup and teardown functions and so on - see nose.tools for more information. +This module provides a set of useful decorators meant to be ready to use in +your own tests. See the bottom of the file for the ready-made ones, and if you +find yourself writing a new one that may be of generic use, add it here. + NOTE: This file contains IPython-specific decorators and imports the numpy.testing.decorators file, which we've copied verbatim. Any of our own code will be added at the bottom if we end up extending this. @@ -15,6 +19,7 @@ code will be added at the bottom if we end up extending this. # Stdlib imports import inspect +import sys # Third-party imports @@ -123,6 +128,9 @@ skip_doctest = make_label_dec('skip_doctest', def skip(msg=''): """Decorator - mark a test function for skipping from test suite. + This function *is* already a decorator, it is not a factory like + make_label_dec or some of those in decorators_numpy. + :Parameters: func : function @@ -145,3 +153,8 @@ def skip(msg=''): return apply_wrapper(wrapper,func) return inner + +# Decorators to skip certain tests on specific platforms. +skip_win32 = skipif(sys.platform=='win32',"This test does not run under Windows") +skip_linux = skipif(sys.platform=='linux2',"This test does not run under Linux") +skip_osx = skipif(sys.platform=='darwin',"This test does not run under OSX") diff --git a/IPython/testing/plugin/test_refs.py b/IPython/testing/plugin/test_refs.py index fc7e6f0..ae9ba41 100644 --- a/IPython/testing/plugin/test_refs.py +++ b/IPython/testing/plugin/test_refs.py @@ -1,152 +1,19 @@ +"""Some simple tests for the plugin while running scripts. +""" # Module imports # Std lib import inspect -# Third party - # Our own from IPython.testing import decorators as dec #----------------------------------------------------------------------------- -# Utilities - -# Note: copied from OInspect, kept here so the testing stuff doesn't create -# circular dependencies and is easier to reuse. -def getargspec(obj): - """Get the names and default values of a function's arguments. - - A tuple of four things is returned: (args, varargs, varkw, defaults). - 'args' is a list of the argument names (it may contain nested lists). - 'varargs' and 'varkw' are the names of the * and ** arguments or None. - 'defaults' is an n-tuple of the default values of the last n arguments. - - Modified version of inspect.getargspec from the Python Standard - Library.""" - - if inspect.isfunction(obj): - func_obj = obj - elif inspect.ismethod(obj): - func_obj = obj.im_func - else: - raise TypeError, 'arg is not a Python function' - args, varargs, varkw = inspect.getargs(func_obj.func_code) - return args, varargs, varkw, func_obj.func_defaults - -#----------------------------------------------------------------------------- # Testing functions def test_trivial(): """A trivial passing test.""" pass - -@dec.skip -def test_deliberately_broken(): - """A deliberately broken test - we want to skip this one.""" - 1/0 - -@dec.skip('foo') -def test_deliberately_broken2(): - """Another deliberately broken test - we want to skip this one.""" - 1/0 - - -# Verify that we can correctly skip the doctest for a function at will, but -# that the docstring itself is NOT destroyed by the decorator. -@dec.skip_doctest -def doctest_bad(x,y=1,**k): - """A function whose doctest we need to skip. - - >>> 1+1 - 3 - """ - print 'x:',x - print 'y:',y - print 'k:',k - - -def call_doctest_bad(): - """Check that we can still call the decorated functions. - - >>> doctest_bad(3,y=4) - x: 3 - y: 4 - k: {} - """ - pass - - -# Doctest skipping should work for class methods too -class foo(object): - """Foo - - Example: - - >>> 1+1 - 2 - """ - - @dec.skip_doctest - def __init__(self,x): - """Make a foo. - - Example: - - >>> f = foo(3) - junk - """ - print 'Making a foo.' - self.x = x - - @dec.skip_doctest - def bar(self,y): - """Example: - - >>> f = foo(3) - >>> f.bar(0) - boom! - >>> 1/0 - bam! - """ - return 1/y - - def baz(self,y): - """Example: - - >>> f = foo(3) - Making a foo. - >>> f.baz(3) - True - """ - return self.x==y - - -def test_skip_dt_decorator(): - """Doctest-skipping decorator should preserve the docstring. - """ - # Careful: 'check' must be a *verbatim* copy of the doctest_bad docstring! - check = """A function whose doctest we need to skip. - - >>> 1+1 - 3 - """ - # Fetch the docstring from doctest_bad after decoration. - val = doctest_bad.__doc__ - - assert check==val,"doctest_bad docstrings don't match" - - -def test_skip_dt_decorator2(): - """Doctest-skipping decorator should preserve function signature. - """ - # Hardcoded correct answer - dtargs = (['x', 'y'], None, 'k', (1,)) - # Introspect out the value - dtargsr = getargspec(doctest_bad) - assert dtargsr==dtargs, \ - "Incorrectly reconstructed args for doctest_bad: %s" % (dtargsr,) - - def doctest_run(): """Test running a trivial script. @@ -154,7 +21,6 @@ def doctest_run(): x is: 1 """ -#@dec.skip_doctest def doctest_runvars(): """Test that variables defined in scripts get loaded correcly via %run. diff --git a/IPython/testing/tests/test_decorators.py b/IPython/testing/tests/test_decorators.py new file mode 100644 index 0000000..e91ec73 --- /dev/null +++ b/IPython/testing/tests/test_decorators.py @@ -0,0 +1,161 @@ +"""Tests for the decorators we've created for IPython. +""" + +# Module imports +# Std lib +import inspect +import sys + +# Third party +import nose.tools as nt + +# Our own +from IPython.testing import decorators as dec + + +#----------------------------------------------------------------------------- +# Utilities + +# Note: copied from OInspect, kept here so the testing stuff doesn't create +# circular dependencies and is easier to reuse. +def getargspec(obj): + """Get the names and default values of a function's arguments. + + A tuple of four things is returned: (args, varargs, varkw, defaults). + 'args' is a list of the argument names (it may contain nested lists). + 'varargs' and 'varkw' are the names of the * and ** arguments or None. + 'defaults' is an n-tuple of the default values of the last n arguments. + + Modified version of inspect.getargspec from the Python Standard + Library.""" + + if inspect.isfunction(obj): + func_obj = obj + elif inspect.ismethod(obj): + func_obj = obj.im_func + else: + raise TypeError, 'arg is not a Python function' + args, varargs, varkw = inspect.getargs(func_obj.func_code) + return args, varargs, varkw, func_obj.func_defaults + +#----------------------------------------------------------------------------- +# Testing functions + +@dec.skip +def test_deliberately_broken(): + """A deliberately broken test - we want to skip this one.""" + 1/0 + +@dec.skip('foo') +def test_deliberately_broken2(): + """Another deliberately broken test - we want to skip this one.""" + 1/0 + + +# Verify that we can correctly skip the doctest for a function at will, but +# that the docstring itself is NOT destroyed by the decorator. +@dec.skip_doctest +def doctest_bad(x,y=1,**k): + """A function whose doctest we need to skip. + + >>> 1+1 + 3 + """ + print 'x:',x + print 'y:',y + print 'k:',k + + +def call_doctest_bad(): + """Check that we can still call the decorated functions. + + >>> doctest_bad(3,y=4) + x: 3 + y: 4 + k: {} + """ + pass + + +def test_skip_dt_decorator(): + """Doctest-skipping decorator should preserve the docstring. + """ + # Careful: 'check' must be a *verbatim* copy of the doctest_bad docstring! + check = """A function whose doctest we need to skip. + + >>> 1+1 + 3 + """ + # Fetch the docstring from doctest_bad after decoration. + val = doctest_bad.__doc__ + + assert check==val,"doctest_bad docstrings don't match" + +# Doctest skipping should work for class methods too +class foo(object): + """Foo + + Example: + + >>> 1+1 + 2 + """ + + @dec.skip_doctest + def __init__(self,x): + """Make a foo. + + Example: + + >>> f = foo(3) + junk + """ + print 'Making a foo.' + self.x = x + + @dec.skip_doctest + def bar(self,y): + """Example: + + >>> f = foo(3) + >>> f.bar(0) + boom! + >>> 1/0 + bam! + """ + return 1/y + + def baz(self,y): + """Example: + + >>> f = foo(3) + Making a foo. + >>> f.baz(3) + True + """ + return self.x==y + + + +def test_skip_dt_decorator2(): + """Doctest-skipping decorator should preserve function signature. + """ + # Hardcoded correct answer + dtargs = (['x', 'y'], None, 'k', (1,)) + # Introspect out the value + dtargsr = getargspec(doctest_bad) + assert dtargsr==dtargs, \ + "Incorrectly reconstructed args for doctest_bad: %s" % (dtargsr,) + + +@dec.skip_linux +def test_linux(): + nt.assert_not_equals(sys.platform,'linux2',"This test can't run under linux") + +@dec.skip_win32 +def test_win32(): + nt.assert_not_equals(sys.platform,'win32',"This test can't run under windows") + +@dec.skip_osx +def test_osx(): + nt.assert_not_equals(sys.platform,'darwin',"This test can't run under osx")