##// END OF EJS Templates
skip tests when display variable is not set
Paul Ivanov -
Show More
@@ -1,80 +1,82 b''
1 1 # Standard library imports
2 2 import unittest
3 3
4 4 # System library imports
5 5 from IPython.external.qt import QtCore, QtGui
6 6
7 7 # Local imports
8 8 from IPython.qt.console.console_widget import ConsoleWidget
9 import IPython.testing.decorators as dec
9 10
11 setup = dec.skip_file_no_x11(__name__)
10 12
11 13 class TestConsoleWidget(unittest.TestCase):
12 14
13 15 @classmethod
14 16 def setUpClass(cls):
15 17 """ Create the application for the test case.
16 18 """
17 19 cls._app = QtGui.QApplication.instance()
18 20 if cls._app is None:
19 21 cls._app = QtGui.QApplication([])
20 22 cls._app.setQuitOnLastWindowClosed(False)
21 23
22 24 @classmethod
23 25 def tearDownClass(cls):
24 26 """ Exit the application.
25 27 """
26 28 QtGui.QApplication.quit()
27 29
28 30 def test_special_characters(self):
29 31 """ Are special characters displayed correctly?
30 32 """
31 33 w = ConsoleWidget()
32 34 cursor = w._get_prompt_cursor()
33 35
34 36 test_inputs = ['xyz\b\b=\n', 'foo\b\nbar\n', 'foo\b\nbar\r\n', 'abc\rxyz\b\b=']
35 37 expected_outputs = [u'x=z\u2029', u'foo\u2029bar\u2029', u'foo\u2029bar\u2029', 'x=z']
36 38 for i, text in enumerate(test_inputs):
37 39 w._insert_plain_text(cursor, text)
38 40 cursor.select(cursor.Document)
39 41 selection = cursor.selectedText()
40 42 self.assertEqual(expected_outputs[i], selection)
41 43 # clear all the text
42 44 cursor.insertText('')
43 45
44 46 def test_link_handling(self):
45 47 noKeys = QtCore.Qt
46 48 noButton = QtCore.Qt.MouseButton(0)
47 49 noButtons = QtCore.Qt.MouseButtons(0)
48 50 noModifiers = QtCore.Qt.KeyboardModifiers(0)
49 51 MouseMove = QtCore.QEvent.MouseMove
50 52 QMouseEvent = QtGui.QMouseEvent
51 53
52 54 w = ConsoleWidget()
53 55 cursor = w._get_prompt_cursor()
54 56 w._insert_html(cursor, '<a href="http://python.org">written in</a>')
55 57 obj = w._control
56 58 tip = QtGui.QToolTip
57 59 self.assertEqual(tip.text(), u'')
58 60
59 61 # should be somewhere else
60 62 elsewhereEvent = QMouseEvent(MouseMove, QtCore.QPoint(50,50),
61 63 noButton, noButtons, noModifiers)
62 64 w.eventFilter(obj, elsewhereEvent)
63 65 self.assertEqual(tip.isVisible(), False)
64 66 self.assertEqual(tip.text(), u'')
65 67
66 68 #self.assertEqual(tip.text(), u'')
67 69 # should be over text
68 70 overTextEvent = QMouseEvent(MouseMove, QtCore.QPoint(1,5),
69 71 noButton, noButtons, noModifiers)
70 72 w.eventFilter(obj, overTextEvent)
71 73 self.assertEqual(tip.isVisible(), True)
72 74 self.assertEqual(tip.text(), "http://python.org")
73 75
74 76 # should still be over text
75 77 stillOverTextEvent = QMouseEvent(MouseMove, QtCore.QPoint(1,5),
76 78 noButton, noButtons, noModifiers)
77 79 w.eventFilter(obj, stillOverTextEvent)
78 80 self.assertEqual(tip.isVisible(), True)
79 81 self.assertEqual(tip.text(), "http://python.org")
80 82
@@ -1,85 +1,87 b''
1 1 # Standard library imports
2 2 import unittest
3 3
4 4 # System library imports
5 5 from IPython.external.qt import QtGui
6 6
7 7 # Local imports
8 8 from IPython.qt.console.kill_ring import KillRing, QtKillRing
9 import IPython.testing.decorators as dec
9 10
11 setup = dec.skip_file_no_x11(__name__)
10 12
11 13 class TestKillRing(unittest.TestCase):
12 14
13 15 @classmethod
14 16 def setUpClass(cls):
15 17 """ Create the application for the test case.
16 18 """
17 19 cls._app = QtGui.QApplication.instance()
18 20 if cls._app is None:
19 21 cls._app = QtGui.QApplication([])
20 22 cls._app.setQuitOnLastWindowClosed(False)
21 23
22 24 @classmethod
23 25 def tearDownClass(cls):
24 26 """ Exit the application.
25 27 """
26 28 QtGui.QApplication.quit()
27 29
28 30 def test_generic(self):
29 31 """ Does the generic kill ring work?
30 32 """
31 33 ring = KillRing()
32 34 self.assertTrue(ring.yank() is None)
33 35 self.assertTrue(ring.rotate() is None)
34 36
35 37 ring.kill('foo')
36 38 self.assertEqual(ring.yank(), 'foo')
37 39 self.assertTrue(ring.rotate() is None)
38 40 self.assertEqual(ring.yank(), 'foo')
39 41
40 42 ring.kill('bar')
41 43 self.assertEqual(ring.yank(), 'bar')
42 44 self.assertEqual(ring.rotate(), 'foo')
43 45
44 46 ring.clear()
45 47 self.assertTrue(ring.yank() is None)
46 48 self.assertTrue(ring.rotate() is None)
47 49
48 50 def test_qt_basic(self):
49 51 """ Does the Qt kill ring work?
50 52 """
51 53 text_edit = QtGui.QPlainTextEdit()
52 54 ring = QtKillRing(text_edit)
53 55
54 56 ring.kill('foo')
55 57 ring.kill('bar')
56 58 ring.yank()
57 59 ring.rotate()
58 60 ring.yank()
59 61 self.assertEqual(text_edit.toPlainText(), 'foobar')
60 62
61 63 text_edit.clear()
62 64 ring.kill('baz')
63 65 ring.yank()
64 66 ring.rotate()
65 67 ring.rotate()
66 68 ring.rotate()
67 69 self.assertEqual(text_edit.toPlainText(), 'foo')
68 70
69 71 def test_qt_cursor(self):
70 72 """ Does the Qt kill ring maintain state with cursor movement?
71 73 """
72 74 text_edit = QtGui.QPlainTextEdit()
73 75 ring = QtKillRing(text_edit)
74 76
75 77 ring.kill('foo')
76 78 ring.kill('bar')
77 79 ring.yank()
78 80 text_edit.moveCursor(QtGui.QTextCursor.Left)
79 81 ring.rotate()
80 82 self.assertEqual(text_edit.toPlainText(), 'bar')
81 83
82 84
83 85 if __name__ == '__main__':
84 86 import nose
85 87 nose.main()
@@ -1,366 +1,391 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Decorators for labeling test objects.
3 3
4 4 Decorators that merely return a modified version of the original function
5 5 object are straightforward. Decorators that return a new function object need
6 6 to use nose.tools.make_decorator(original_function)(decorator) in returning the
7 7 decorator, in order to preserve metadata such as function name, setup and
8 8 teardown functions and so on - see nose.tools for more information.
9 9
10 10 This module provides a set of useful decorators meant to be ready to use in
11 11 your own tests. See the bottom of the file for the ready-made ones, and if you
12 12 find yourself writing a new one that may be of generic use, add it here.
13 13
14 14 Included decorators:
15 15
16 16
17 17 Lightweight testing that remains unittest-compatible.
18 18
19 19 - @parametric, for parametric test support that is vastly easier to use than
20 20 nose's for debugging. With ours, if a test fails, the stack under inspection
21 21 is that of the test and not that of the test framework.
22 22
23 23 - An @as_unittest decorator can be used to tag any normal parameter-less
24 24 function as a unittest TestCase. Then, both nose and normal unittest will
25 25 recognize it as such. This will make it easier to migrate away from Nose if
26 26 we ever need/want to while maintaining very lightweight tests.
27 27
28 28 NOTE: This file contains IPython-specific decorators. Using the machinery in
29 29 IPython.external.decorators, we import either numpy.testing.decorators if numpy is
30 30 available, OR use equivalent code in IPython.external._decorators, which
31 31 we've copied verbatim from numpy.
32 32
33 33 Authors
34 34 -------
35 35
36 36 - Fernando Perez <Fernando.Perez@berkeley.edu>
37 37 """
38 38
39 39 #-----------------------------------------------------------------------------
40 40 # Copyright (C) 2009-2011 The IPython Development Team
41 41 #
42 42 # Distributed under the terms of the BSD License. The full license is in
43 43 # the file COPYING, distributed as part of this software.
44 44 #-----------------------------------------------------------------------------
45 45
46 46 #-----------------------------------------------------------------------------
47 47 # Imports
48 48 #-----------------------------------------------------------------------------
49 49
50 50 # Stdlib imports
51 51 import sys
52 import os
52 53 import tempfile
53 54 import unittest
54 55
55 56 # Third-party imports
56 57
57 58 # This is Michele Simionato's decorator module, kept verbatim.
58 59 from IPython.external.decorator import decorator
59 60
60 61 # We already have python3-compliant code for parametric tests
61 62 if sys.version[0]=='2':
62 63 from _paramtestpy2 import parametric
63 64 else:
64 65 from _paramtestpy3 import parametric
65 66
66 67 # Expose the unittest-driven decorators
67 68 from ipunittest import ipdoctest, ipdocstring
68 69
69 70 # Grab the numpy-specific decorators which we keep in a file that we
70 71 # occasionally update from upstream: decorators.py is a copy of
71 72 # numpy.testing.decorators, we expose all of it here.
72 73 from IPython.external.decorators import *
73 74
74 75 # For onlyif_cmd_exists decorator
75 76 from IPython.utils.process import is_cmd_found
76 77
77 78 #-----------------------------------------------------------------------------
78 79 # Classes and functions
79 80 #-----------------------------------------------------------------------------
80 81
81 82 # Simple example of the basic idea
82 83 def as_unittest(func):
83 84 """Decorator to make a simple function into a normal test via unittest."""
84 85 class Tester(unittest.TestCase):
85 86 def test(self):
86 87 func()
87 88
88 89 Tester.__name__ = func.__name__
89 90
90 91 return Tester
91 92
92 93 # Utility functions
93 94
94 95 def apply_wrapper(wrapper,func):
95 96 """Apply a wrapper to a function for decoration.
96 97
97 98 This mixes Michele Simionato's decorator tool with nose's make_decorator,
98 99 to apply a wrapper in a decorator so that all nose attributes, as well as
99 100 function signature and other properties, survive the decoration cleanly.
100 101 This will ensure that wrapped functions can still be well introspected via
101 102 IPython, for example.
102 103 """
103 104 import nose.tools
104 105
105 106 return decorator(wrapper,nose.tools.make_decorator(func)(wrapper))
106 107
107 108
108 109 def make_label_dec(label,ds=None):
109 110 """Factory function to create a decorator that applies one or more labels.
110 111
111 112 Parameters
112 113 ----------
113 114 label : string or sequence
114 115 One or more labels that will be applied by the decorator to the functions
115 116 it decorates. Labels are attributes of the decorated function with their
116 117 value set to True.
117 118
118 119 ds : string
119 120 An optional docstring for the resulting decorator. If not given, a
120 121 default docstring is auto-generated.
121 122
122 123 Returns
123 124 -------
124 125 A decorator.
125 126
126 127 Examples
127 128 --------
128 129
129 130 A simple labeling decorator:
130 131
131 132 >>> slow = make_label_dec('slow')
132 133 >>> slow.__doc__
133 134 "Labels a test as 'slow'."
134 135
135 136 And one that uses multiple labels and a custom docstring:
136 137
137 138 >>> rare = make_label_dec(['slow','hard'],
138 139 ... "Mix labels 'slow' and 'hard' for rare tests.")
139 140 >>> rare.__doc__
140 141 "Mix labels 'slow' and 'hard' for rare tests."
141 142
142 143 Now, let's test using this one:
143 144 >>> @rare
144 145 ... def f(): pass
145 146 ...
146 147 >>>
147 148 >>> f.slow
148 149 True
149 150 >>> f.hard
150 151 True
151 152 """
152 153
153 154 if isinstance(label,basestring):
154 155 labels = [label]
155 156 else:
156 157 labels = label
157 158
158 159 # Validate that the given label(s) are OK for use in setattr() by doing a
159 160 # dry run on a dummy function.
160 161 tmp = lambda : None
161 162 for label in labels:
162 163 setattr(tmp,label,True)
163 164
164 165 # This is the actual decorator we'll return
165 166 def decor(f):
166 167 for label in labels:
167 168 setattr(f,label,True)
168 169 return f
169 170
170 171 # Apply the user's docstring, or autogenerate a basic one
171 172 if ds is None:
172 173 ds = "Labels a test as %r." % label
173 174 decor.__doc__ = ds
174 175
175 176 return decor
176 177
177 178
178 179 # Inspired by numpy's skipif, but uses the full apply_wrapper utility to
179 180 # preserve function metadata better and allows the skip condition to be a
180 181 # callable.
181 182 def skipif(skip_condition, msg=None):
182 183 ''' Make function raise SkipTest exception if skip_condition is true
183 184
184 185 Parameters
185 186 ----------
186 187 skip_condition : bool or callable.
187 188 Flag to determine whether to skip test. If the condition is a
188 189 callable, it is used at runtime to dynamically make the decision. This
189 190 is useful for tests that may require costly imports, to delay the cost
190 191 until the test suite is actually executed.
191 192 msg : string
192 193 Message to give on raising a SkipTest exception
193 194
194 195 Returns
195 196 -------
196 197 decorator : function
197 198 Decorator, which, when applied to a function, causes SkipTest
198 199 to be raised when the skip_condition was True, and the function
199 200 to be called normally otherwise.
200 201
201 202 Notes
202 203 -----
203 204 You will see from the code that we had to further decorate the
204 205 decorator with the nose.tools.make_decorator function in order to
205 206 transmit function name, and various other metadata.
206 207 '''
207 208
208 209 def skip_decorator(f):
209 210 # Local import to avoid a hard nose dependency and only incur the
210 211 # import time overhead at actual test-time.
211 212 import nose
212 213
213 214 # Allow for both boolean or callable skip conditions.
214 215 if callable(skip_condition):
215 216 skip_val = skip_condition
216 217 else:
217 218 skip_val = lambda : skip_condition
218 219
219 220 def get_msg(func,msg=None):
220 221 """Skip message with information about function being skipped."""
221 222 if msg is None: out = 'Test skipped due to test condition.'
222 223 else: out = msg
223 224 return "Skipping test: %s. %s" % (func.__name__,out)
224 225
225 226 # We need to define *two* skippers because Python doesn't allow both
226 227 # return with value and yield inside the same function.
227 228 def skipper_func(*args, **kwargs):
228 229 """Skipper for normal test functions."""
229 230 if skip_val():
230 231 raise nose.SkipTest(get_msg(f,msg))
231 232 else:
232 233 return f(*args, **kwargs)
233 234
234 235 def skipper_gen(*args, **kwargs):
235 236 """Skipper for test generators."""
236 237 if skip_val():
237 238 raise nose.SkipTest(get_msg(f,msg))
238 239 else:
239 240 for x in f(*args, **kwargs):
240 241 yield x
241 242
242 243 # Choose the right skipper to use when building the actual generator.
243 244 if nose.util.isgenerator(f):
244 245 skipper = skipper_gen
245 246 else:
246 247 skipper = skipper_func
247 248
248 249 return nose.tools.make_decorator(f)(skipper)
249 250
250 251 return skip_decorator
251 252
252 253 # A version with the condition set to true, common case just to attach a message
253 254 # to a skip decorator
254 255 def skip(msg=None):
255 256 """Decorator factory - mark a test function for skipping from test suite.
256 257
257 258 Parameters
258 259 ----------
259 260 msg : string
260 261 Optional message to be added.
261 262
262 263 Returns
263 264 -------
264 265 decorator : function
265 266 Decorator, which, when applied to a function, causes SkipTest
266 267 to be raised, with the optional message added.
267 268 """
268 269
269 270 return skipif(True,msg)
270 271
271 272
272 273 def onlyif(condition, msg):
273 274 """The reverse from skipif, see skipif for details."""
274 275
275 276 if callable(condition):
276 277 skip_condition = lambda : not condition()
277 278 else:
278 279 skip_condition = lambda : not condition
279 280
280 281 return skipif(skip_condition, msg)
281 282
282 283 #-----------------------------------------------------------------------------
283 284 # Utility functions for decorators
284 285 def module_not_available(module):
285 286 """Can module be imported? Returns true if module does NOT import.
286 287
287 288 This is used to make a decorator to skip tests that require module to be
288 289 available, but delay the 'import numpy' to test execution time.
289 290 """
290 291 try:
291 292 mod = __import__(module)
292 293 mod_not_avail = False
293 294 except ImportError:
294 295 mod_not_avail = True
295 296
296 297 return mod_not_avail
297 298
299
300 def decorated_dummy(dec, name):
301 """Return a dummy function decorated with dec, with the given name.
302
303 Examples
304 --------
305 import IPython.testing.decorators as dec
306 setup = dec.decorated_dummy(dec.skip_if_no_x11, __name__)
307 """
308 dummy = lambda: None
309 dummy.__name__ = name
310 return dec(dummy)
311
298 312 #-----------------------------------------------------------------------------
299 313 # Decorators for public use
300 314
301 315 # Decorators to skip certain tests on specific platforms.
302 316 skip_win32 = skipif(sys.platform == 'win32',
303 317 "This test does not run under Windows")
304 318 skip_linux = skipif(sys.platform.startswith('linux'),
305 319 "This test does not run under Linux")
306 320 skip_osx = skipif(sys.platform == 'darwin',"This test does not run under OS X")
307 321
308 322
309 323 # Decorators to skip tests if not on specific platforms.
310 324 skip_if_not_win32 = skipif(sys.platform != 'win32',
311 325 "This test only runs under Windows")
312 326 skip_if_not_linux = skipif(not sys.platform.startswith('linux'),
313 327 "This test only runs under Linux")
314 328 skip_if_not_osx = skipif(sys.platform != 'darwin',
315 329 "This test only runs under OSX")
316 330
331
332 _x11_skip_cond = (sys.platform not in ('darwin', 'win32') and
333 os.environ['DISPLAY']=='')
334 _x11_skip_msg = "Skipped under *nix when X11/XOrg not available"
335
336 skip_if_no_x11 = skipif(_x11_skip_cond, _x11_skip_msg)
337
338 # not a decorator itself, returns a dummy function to be used as setup
339 def skip_file_no_x11(name):
340 return decorated_dummy(skip_if_no_x11, name) if _x11_skip_cond else None
341
317 342 # Other skip decorators
318 343
319 344 # generic skip without module
320 345 skip_without = lambda mod: skipif(module_not_available(mod), "This test requires %s" % mod)
321 346
322 347 skipif_not_numpy = skip_without('numpy')
323 348
324 349 skipif_not_matplotlib = skip_without('matplotlib')
325 350
326 351 skipif_not_sympy = skip_without('sympy')
327 352
328 353 skip_known_failure = knownfailureif(True,'This test is known to fail')
329 354
330 355 known_failure_py3 = knownfailureif(sys.version_info[0] >= 3,
331 356 'This test is known to fail on Python 3.')
332 357
333 358 # A null 'decorator', useful to make more readable code that needs to pick
334 359 # between different decorators based on OS or other conditions
335 360 null_deco = lambda f: f
336 361
337 362 # Some tests only run where we can use unicode paths. Note that we can't just
338 363 # check os.path.supports_unicode_filenames, which is always False on Linux.
339 364 try:
340 365 f = tempfile.NamedTemporaryFile(prefix=u"tmp€")
341 366 except UnicodeEncodeError:
342 367 unicode_paths = False
343 368 else:
344 369 unicode_paths = True
345 370 f.close()
346 371
347 372 onlyif_unicode_paths = onlyif(unicode_paths, ("This test is only applicable "
348 373 "where we can use unicode in filenames."))
349 374
350 375
351 376 def onlyif_cmds_exist(*commands):
352 377 """
353 378 Decorator to skip test when at least one of `commands` is not found.
354 379 """
355 380 for cmd in commands:
356 381 try:
357 382 if not is_cmd_found(cmd):
358 383 return skip("This test runs only if command '{0}' "
359 384 "is installed".format(cmd))
360 385 except ImportError as e:
361 386 # is_cmd_found uses pywin32 on windows, which might not be available
362 387 if sys.platform == 'win32' and 'pywin32' in e.message:
363 388 return skip("This test runs only if pywin32 and command '{0}' "
364 389 "is installed".format(cmd))
365 390 raise e
366 391 return null_deco
General Comments 0
You need to be logged in to leave comments. Login now