Skip to content

Commit

Permalink
Backports for:
Browse files Browse the repository at this point in the history
  rev 5769 - Replaced numpy.testing.decorators.skipknownfailure with 
             knownfailureif, which allows flagging tests as known failures
             rather than skips.  Updated test_umath to use knownfailureif.
  rev 5770 - Renamed classes in nosetester.py/noseclasses.py to
             conform to PEP 8.
  rev 5772 - Removed debugging code from noseclasses.py
  • Loading branch information
Alan McIntyre committed Sep 6, 2008
1 parent 426e008 commit 64cfd38
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 24 deletions.
2 changes: 1 addition & 1 deletion numpy/core/tests/test_umath.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ def test_branch_cuts(self):
yield _check_branch_cut, np.arccosh, [-2j, 2j, 2], [1, 1, 1j], 1, 1
yield _check_branch_cut, np.arctanh, [-2j, 2j, 0], [1, 1, 1j], 1, 1

@dec.knownfailureif(True, "These branch cuts are known to fail")
def test_branch_cuts_failing(self):
# XXX: signed zeros are not OK for sqrt or for the arc* functions
yield _check_branch_cut, np.sqrt, -0.5, 1j, 1, -1, True
Expand All @@ -238,7 +239,6 @@ def test_branch_cuts_failing(self):
yield _check_branch_cut, np.arcsinh, [-2j, 2j], [-1, 1], -1, 1, True
yield _check_branch_cut, np.arccosh, [ -1, 0.5], [1j, 1j], 1, -1, True
yield _check_branch_cut, np.arctanh, [ -2, 2], [1j, -1j], 1, -1, True
test_branch_cuts_failing = dec.skipknownfailure(test_branch_cuts_failing)

def test_against_cmath(self):
import cmath, sys
Expand Down
45 changes: 37 additions & 8 deletions numpy/testing/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,41 @@ def skipper(*args, **kwargs):
return nose.tools.make_decorator(f)(skipper)
return skip_decorator

def skipknownfailure(f):
''' Decorator to raise SkipTest for test known to fail
def knownfailureif(skip_condition, msg=None):
''' Make function raise KnownFailureTest exception if skip_condition is true
Parameters
---------
skip_condition : bool
Flag to determine whether to mark test as known failure (True)
or not (False)
msg : string
Message to give on raising a KnownFailureTest exception
Returns
-------
decorator : function
Decorator, which, when applied to a function, causes SkipTest
to be raised when the skip_condition was True, and the function
to be called normally otherwise.
Notes
-----
You will see from the code that we had to further decorate the
decorator with the nose.tools.make_decorator function in order to
transmit function name, and various other metadata.
'''
# Local import to avoid a hard nose dependency and only incur the
# import time overhead at actual test-time.
import nose
def skipper(*args, **kwargs):
raise nose.SkipTest, 'This test is known to fail'
return nose.tools.make_decorator(f)(skipper)
if msg is None:
msg = 'Test skipped due to known failure'
def skip_decorator(f):
# Local import to avoid a hard nose dependency and only incur the
# import time overhead at actual test-time.
import nose
from noseclasses import KnownFailureTest
def skipper(*args, **kwargs):
if skip_condition:
raise KnownFailureTest, msg
else:
return f(*args, **kwargs)
return nose.tools.make_decorator(f)(skipper)
return skip_decorator
56 changes: 43 additions & 13 deletions numpy/testing/noseclasses.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import doctest

from nose.plugins import doctests as npd
from nose.plugins.errorclass import ErrorClass, ErrorClassPlugin
from nose.plugins.base import Plugin
from nose.util import src, tolist
import numpy
Expand All @@ -16,14 +17,14 @@
_doctest_ignore = ['generate_numpy_api.py', 'scons_support.py',
'setupscons.py', 'setup.py']

# All the classes in this module begin with 'numpy' to clearly distinguish them
# from the plethora of very similar names from nose/unittest/doctest
# Some of the classes in this module begin with 'Numpy' to clearly distinguish
# them from the plethora of very similar names from nose/unittest/doctest


#-----------------------------------------------------------------------------
# Modified version of the one in the stdlib, that fixes a python bug (doctests
# not found in extension modules, http://bugs.python.org/issue3158)
class numpyDocTestFinder(doctest.DocTestFinder):
class NumpyDocTestFinder(doctest.DocTestFinder):

def _from_module(self, module, object):
"""
Expand Down Expand Up @@ -113,7 +114,7 @@ def _find(self, tests, obj, name, module, source_lines, globs, seen):
globs, seen)


class numpyDocTestCase(npd.DocTestCase):
class NumpyDocTestCase(npd.DocTestCase):
"""Proxy for DocTestCase: provides an address() method that
returns the correct address for the doctest case. Otherwise
acts as a proxy to the test case. To provide hints for address(),
Expand All @@ -137,7 +138,7 @@ def id(self):
# second-chance checker; if the default comparison doesn't
# pass, then see if the expected output string contains flags that
# tell us to ignore the output
class numpyOutputChecker(doctest.OutputChecker):
class NumpyOutputChecker(doctest.OutputChecker):
def check_output(self, want, got, optionflags):
ret = doctest.OutputChecker.check_output(self, want, got,
optionflags)
Expand All @@ -151,7 +152,7 @@ def check_output(self, want, got, optionflags):
# Subclass nose.plugins.doctests.DocTestCase to work around a bug in
# its constructor that blocks non-default arguments from being passed
# down into doctest.DocTestCase
class numpyDocTestCase(npd.DocTestCase):
class NumpyDocTestCase(npd.DocTestCase):
def __init__(self, test, optionflags=0, setUp=None, tearDown=None,
checker=None, obj=None, result_var='_'):
self._result_var = result_var
Expand All @@ -164,7 +165,7 @@ def __init__(self, test, optionflags=0, setUp=None, tearDown=None,

print_state = numpy.get_printoptions()

class numpyDoctest(npd.Doctest):
class NumpyDoctest(npd.Doctest):
name = 'numpydoctest' # call nosetests with --with-numpydoctest
enabled = True

Expand All @@ -175,7 +176,7 @@ def configure(self, options, config):
Plugin.configure(self, options, config)
self.doctest_tests = True
# self.extension = tolist(options.doctestExtension)
self.finder = numpyDocTestFinder()
self.finder = NumpyDocTestFinder()
self.parser = doctest.DocTestParser()

# Turn on whitespace normalization, set a minimal execution context
Expand Down Expand Up @@ -223,15 +224,12 @@ def loadTestsFromModule(self, module):
p2 = p[-1]
test.globs[p2] = __import__(pkg_name, test.globs, {}, [p2])

print 'additional import for %s: from %s import %s' % (test.filename, p1, p2)
print ' (%s): %r' % (pkg_name, test.globs[p2])

# always use whitespace and ellipsis options
optionflags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS

yield numpyDocTestCase(test,
yield NumpyDocTestCase(test,
optionflags=optionflags,
checker=numpyOutputChecker())
checker=NumpyOutputChecker())


# Add an afterContext method to nose.plugins.doctests.Doctest in order
Expand All @@ -246,3 +244,35 @@ def wantFile(self, file):
if bn in _doctest_ignore:
return False
return npd.Doctest.wantFile(self, file)


class KnownFailureTest(Exception):
'''Raise this exception to mark a test as a known failing test.'''
pass


class KnownFailure(ErrorClassPlugin):
'''Plugin that installs a KNOWNFAIL error class for the
KnownFailureClass exception. When KnownFailureTest is raised,
the exception will be logged in the knownfail attribute of the
result, 'K' or 'KNOWNFAIL' (verbose) will be output, and the
exception will not be counted as an error or failure.'''
enabled = True
knownfail = ErrorClass(KnownFailureTest,
label='KNOWNFAIL',
isfailure=False)

def options(self, parser, env=os.environ):
env_opt = 'NOSE_WITHOUT_KNOWNFAIL'
parser.add_option('--no-knownfail', action='store_true',
dest='noKnownFail', default=env.get(env_opt, False),
help='Disable special handling of KnownFailureTest '
'exceptions')

def configure(self, options, conf):
if not self.can_configure:
return
self.conf = conf
disable = getattr(options, 'noKnownFail', False)
if disable:
self.enabled = False
4 changes: 2 additions & 2 deletions numpy/testing/nosetester.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,8 +266,8 @@ def runTests(self):

# construct list of plugins, omitting the existing doctest plugin
import nose.plugins.builtin
from noseclasses import numpyDoctest
plugins = [numpyDoctest()]
from noseclasses import NumpyDoctest, KnownFailure
plugins = [NumpyDoctest(), KnownFailure()]
for p in nose.plugins.builtin.plugins:
plug = p()
if plug.name == 'doctest':
Expand Down

0 comments on commit 64cfd38

Please sign in to comment.