##// END OF EJS Templates
Add optional message to @skip test decorator.
Fernando Perez -
Show More
@@ -1,135 +1,146 b''
1 1 """Decorators for labeling test objects.
2 2
3 3 Decorators that merely return a modified version of the original
4 4 function object are straightforward. Decorators that return a new
5 5 function object need to use
6 6 nose.tools.make_decorator(original_function)(decorator) in returning
7 7 the decorator, in order to preserve metadata such as function name,
8 8 setup and teardown functions and so on - see nose.tools for more
9 9 information.
10 10
11 11 NOTE: This file contains IPython-specific decorators and imports the
12 12 numpy.testing.decorators file, which we've copied verbatim. Any of our own
13 13 code will be added at the bottom if we end up extending this.
14 14 """
15 15
16 16 # Stdlib imports
17 17 import inspect
18 18
19 19 # Third-party imports
20 20
21 21 # This is Michele Simionato's decorator module, also kept verbatim.
22 22 from decorator_msim import decorator, update_wrapper
23 23
24 24 # Grab the numpy-specific decorators which we keep in a file that we
25 25 # occasionally update from upstream: decorators_numpy.py is an IDENTICAL copy
26 26 # of numpy.testing.decorators.
27 27 from decorators_numpy import *
28 28
29 29 ##############################################################################
30 30 # Local code begins
31 31
32 32 # Utility functions
33 33
34 34 def apply_wrapper(wrapper,func):
35 35 """Apply a wrapper to a function for decoration.
36 36
37 37 This mixes Michele Simionato's decorator tool with nose's make_decorator,
38 38 to apply a wrapper in a decorator so that all nose attributes, as well as
39 39 function signature and other properties, survive the decoration cleanly.
40 40 This will ensure that wrapped functions can still be well introspected via
41 41 IPython, for example.
42 42 """
43 43 import nose.tools
44 44
45 45 return decorator(wrapper,nose.tools.make_decorator(func)(wrapper))
46 46
47 47
48 48 def make_label_dec(label,ds=None):
49 49 """Factory function to create a decorator that applies one or more labels.
50 50
51 51 :Parameters:
52 52 label : string or sequence
53 53 One or more labels that will be applied by the decorator to the functions
54 54 it decorates. Labels are attributes of the decorated function with their
55 55 value set to True.
56 56
57 57 :Keywords:
58 58 ds : string
59 59 An optional docstring for the resulting decorator. If not given, a
60 60 default docstring is auto-generated.
61 61
62 62 :Returns:
63 63 A decorator.
64 64
65 65 :Examples:
66 66
67 67 A simple labeling decorator:
68 68 >>> slow = make_label_dec('slow')
69 69 >>> print slow.__doc__
70 70 Labels a test as 'slow'.
71 71
72 72 And one that uses multiple labels and a custom docstring:
73 73 >>> rare = make_label_dec(['slow','hard'],
74 74 ... "Mix labels 'slow' and 'hard' for rare tests.")
75 75 >>> print rare.__doc__
76 76 Mix labels 'slow' and 'hard' for rare tests.
77 77
78 78 Now, let's test using this one:
79 79 >>> @rare
80 80 ... def f(): pass
81 81 ...
82 82 >>>
83 83 >>> f.slow
84 84 True
85 85 >>> f.hard
86 86 True
87 87 """
88 88
89 89 if isinstance(label,basestring):
90 90 labels = [label]
91 91 else:
92 92 labels = label
93 93
94 94 # Validate that the given label(s) are OK for use in setattr() by doing a
95 95 # dry run on a dummy function.
96 96 tmp = lambda : None
97 97 for label in labels:
98 98 setattr(tmp,label,True)
99 99
100 100 # This is the actual decorator we'll return
101 101 def decor(f):
102 102 for label in labels:
103 103 setattr(f,label,True)
104 104 return f
105 105
106 106 # Apply the user's docstring, or autogenerate a basic one
107 107 if ds is None:
108 108 ds = "Labels a test as %r." % label
109 109 decor.__doc__ = ds
110 110
111 111 return decor
112 112
113 113 #-----------------------------------------------------------------------------
114 114 # Decorators for public use
115 115
116 116 skip_doctest = make_label_dec('skip_doctest',
117 117 """Decorator - mark a function or method for skipping its doctest.
118 118
119 119 This decorator allows you to mark a function whose docstring you wish to
120 120 omit from testing, while preserving the docstring for introspection, help,
121 121 etc.""")
122 122
123 123
124 def skip(func):
125 """Decorator - mark a test function for skipping from test suite."""
124 def skip(func,msg=''):
125 """Decorator - mark a test function for skipping from test suite.
126
127 :Parameters:
128
129 func : function
130 Test function to be skipped
131
132 msg : string
133 Optional message to be added.
134 """
126 135
127 136 import nose
128 137
129 138 def wrapper(*a,**k):
130 raise nose.SkipTest("Skipping test for function: %s" %
131 func.__name__)
139 if msg:
140 msg = '\n'+msg
141 raise nose.SkipTest("Skipping test for function: %s%s" %
142 (func.__name__,msg))
132 143
133 144 return apply_wrapper(wrapper,func)
134 145
135 146
General Comments 0
You need to be logged in to leave comments. Login now