From c35373440c83358f3176629642414f276f6298f1 2009-04-23 00:54:49 From: Brian Granger Date: 2009-04-23 00:54:49 Subject: [PATCH] Commiting fixes for running our test suite using trial and nose. We are moving towards a model that allows trial and nose to each run different parts of our test suite. I have added __test__ = {} to modules that nose should skip. I have added new decorators that trial can use to skip tests. See this ticket for more information: https://bugs.launchpad.net/bugs/362142 --- diff --git a/IPython/kernel/core/tests/test_interpreter.py b/IPython/kernel/core/tests/test_interpreter.py index 0db9a13..bee4d9a 100644 --- a/IPython/kernel/core/tests/test_interpreter.py +++ b/IPython/kernel/core/tests/test_interpreter.py @@ -2,29 +2,27 @@ """This file contains unittests for the interpreter.py module.""" -__docformat__ = "restructuredtext en" - #----------------------------------------------------------------------------- -# Copyright (C) 2008-2009 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. +# Copyright (C) 2008-2009 The IPython Development Team +# +# Distributed under the terms of the BSD License. The full license is +# in the file COPYING, distributed as part of this software. #----------------------------------------------------------------------------- #----------------------------------------------------------------------------- -# Imports +# Imports #----------------------------------------------------------------------------- -import unittest +# Tell nose to skip this module +__test__ = {} + +from twisted.trial import unittest from IPython.kernel.core.interpreter import Interpreter #----------------------------------------------------------------------------- -# Tests +# Tests #----------------------------------------------------------------------------- -# Tell nose to skip this module -__test__ = {} - class TestInterpreter(unittest.TestCase): def test_unicode(self): diff --git a/IPython/kernel/core/tests/test_notification.py b/IPython/kernel/core/tests/test_notification.py index 255da35..2744049 100644 --- a/IPython/kernel/core/tests/test_notification.py +++ b/IPython/kernel/core/tests/test_notification.py @@ -2,29 +2,26 @@ """This file contains unittests for the notification.py module.""" -__docformat__ = "restructuredtext en" - #----------------------------------------------------------------------------- -# Copyright (C) 2008 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. +# Copyright (C) 2008-2009 The IPython Development Team +# +# Distributed under the terms of the BSD License. The full license is +# in the file COPYING, distributed as part of this software. #----------------------------------------------------------------------------- - + #----------------------------------------------------------------------------- -# Imports +# Imports #----------------------------------------------------------------------------- # Tell nose to skip this module __test__ = {} -import unittest +from twisted.trial import unittest import IPython.kernel.core.notification as notification -from nose.tools import timed -# -# Supporting test classes -# +#----------------------------------------------------------------------------- +# Support Classes +#----------------------------------------------------------------------------- class Observer(object): """docstring for Observer""" @@ -39,7 +36,6 @@ class Observer(object): self.expectedType, self.expectedSender) - def callback(self, theType, sender, args={}): """callback""" @@ -50,7 +46,6 @@ class Observer(object): assert(args == self.expectedKwArgs) self.recieved = True - def verify(self): """verify""" @@ -60,7 +55,6 @@ class Observer(object): """reset""" self.recieved = False - class Notifier(object): @@ -75,11 +69,10 @@ class Notifier(object): center.post_notification(self.theType, self, **self.kwargs) - -# -# Test Cases -# +#----------------------------------------------------------------------------- +# Tests +#----------------------------------------------------------------------------- class NotificationTests(unittest.TestCase): """docstring for NotificationTests""" @@ -97,7 +90,6 @@ class NotificationTests(unittest.TestCase): observer.verify() - def test_type_specificity(self): """Test that observers are registered by type""" @@ -112,7 +104,6 @@ class NotificationTests(unittest.TestCase): observer.verify() - def test_sender_specificity(self): """Test that observers are registered by sender""" @@ -126,7 +117,6 @@ class NotificationTests(unittest.TestCase): observer.verify() - def test_remove_all_observers(self): """White-box test for remove_all_observers""" @@ -139,8 +129,7 @@ class NotificationTests(unittest.TestCase): notification.sharedCenter.remove_all_observers() self.assert_(len(notification.sharedCenter.observers) == 0, "observers removed") - - + def test_any_sender(self): """test_any_sender""" @@ -156,9 +145,7 @@ class NotificationTests(unittest.TestCase): observer.reset() sender2.post() observer.verify() - - - @timed(.01) + def test_post_performance(self): """Test that post_notification, even with many registered irrelevant observers is fast""" @@ -171,4 +158,4 @@ class NotificationTests(unittest.TestCase): notification.sharedCenter.post_notification('EXPECTED_TYPE', self) o.verify() - + diff --git a/IPython/kernel/core/tests/test_redirectors.py b/IPython/kernel/core/tests/test_redirectors.py index 5b5c6f3..3b0e416 100644 --- a/IPython/kernel/core/tests/test_redirectors.py +++ b/IPython/kernel/core/tests/test_redirectors.py @@ -2,69 +2,77 @@ """ Test the output capture at the OS level, using file descriptors. """ - -__docformat__ = "restructuredtext en" - -#------------------------------------------------------------------------------- -# Copyright (C) 2008 The IPython Development Team +#----------------------------------------------------------------------------- +# Copyright (C) 2008-2009 The IPython Development Team # # Distributed under the terms of the BSD License. The full license is # in the file COPYING, distributed as part of this software. -#------------------------------------------------------------------------------- +#----------------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# Imports +#----------------------------------------------------------------------------- # Tell nose to skip this module __test__ = {} -import os from cStringIO import StringIO +import os + +from twisted.trial import unittest -from IPython.testing import decorators as dec +from IPython.testing import decorators_trial as dec #----------------------------------------------------------------------------- -# Test functions +# Tests +#----------------------------------------------------------------------------- -@dec.skip_win32 -def test_redirector(): - """ Checks that the redirector can be used to do synchronous capture. - """ - from IPython.kernel.core.fd_redirector import FDRedirector - r = FDRedirector() - out = StringIO() - try: - r.start() - for i in range(10): - os.system('echo %ic' % i) - print >>out, r.getvalue(), - print >>out, i - except: - r.stop() - raise - r.stop() - result1 = out.getvalue() - result2 = "".join("%ic\n%i\n" %(i, i) for i in range(10)) - assert result1 == result2 +class TestRedirector(unittest.TestCase): -@dec.skip_win32 -def test_redirector_output_trap(): - """ This test check not only that the redirector_output_trap does + @dec.skip_win32 + def test_redirector(self): + """Checks that the redirector can be used to do synchronous capture. + """ + from IPython.kernel.core.fd_redirector import FDRedirector + r = FDRedirector() + out = StringIO() + try: + r.start() + for i in range(10): + os.system('echo %ic' % i) + print >>out, r.getvalue(), + print >>out, i + except: + r.stop() + raise + r.stop() + result1 = out.getvalue() + result2 = "".join("%ic\n%i\n" %(i, i) for i in range(10)) + self.assertEquals(result1, result2) + + @dec.skip_win32 + def test_redirector_output_trap(self): + """Check the greedy trapping behavior of the traps. + + 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 is by calling the callback ASAP. - """ - from IPython.kernel.core.redirector_output_trap import RedirectorOutputTrap - out = StringIO() - trap = RedirectorOutputTrap(out.write, out.write) - try: - trap.set() - for i in range(10): - os.system('echo %ic' % i) - print "%ip" % i - print >>out, i - except: + """ + from IPython.kernel.core.redirector_output_trap import RedirectorOutputTrap + out = StringIO() + trap = RedirectorOutputTrap(out.write, out.write) + try: + trap.set() + for i in range(10): + os.system('echo %ic' % i) + print "%ip" % i + print >>out, i + except: + trap.unset() + raise trap.unset() - raise - trap.unset() - result1 = out.getvalue() - result2 = "".join("%ic\n%ip\n%i\n" %(i, i, i) for i in range(10)) - assert result1 == result2 - + result1 = out.getvalue() + result2 = "".join("%ic\n%ip\n%i\n" %(i, i, i) for i in range(10)) + self.assertEquals(result1, result2) + diff --git a/IPython/testing/decorators_trial.py b/IPython/testing/decorators_trial.py new file mode 100644 index 0000000..231054b --- /dev/null +++ b/IPython/testing/decorators_trial.py @@ -0,0 +1,132 @@ +# encoding: utf-8 +""" +Testing related decorators for use with twisted.trial. + +The decorators in this files are designed to follow the same API as those +in the decorators module (in this same directory). But they can be used +with twisted.trial +""" + +#----------------------------------------------------------------------------- +# Copyright (C) 2008-2009 The IPython Development Team +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#----------------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# Imports +#----------------------------------------------------------------------------- + +import os +import sys + +from IPython.testing.decorators import make_label_dec + +#----------------------------------------------------------------------------- +# Testing decorators +#----------------------------------------------------------------------------- + + +def skipif(skip_condition, msg=None): + """Create a decorator that marks a test function for skipping. + + The is a decorator factory that returns a decorator that will + conditionally skip a test based on the value of skip_condition. The + skip_condition argument can either be a boolean or a callable that returns + a boolean. + + Parameters + ---------- + skip_condition : boolean or callable + If this evaluates to True, the test is skipped. + msg : str + The message to print if the test is skipped. + + Returns + ------- + decorator : function + The decorator function that can be applied to the test function. + """ + + def skip_decorator(f): + + # Allow for both boolean or callable skip conditions. + if callable(skip_condition): + skip_val = lambda : skip_condition() + else: + skip_val = lambda : skip_condition + + if msg is None: + out = 'Test skipped due to test condition.' + else: + out = msg + final_msg = "Skipping test: %s. %s" % (f.__name__,out) + + if skip_val(): + f.skip = final_msg + + return f + return skip_decorator + + +def skip(msg=None): + """Create a decorator that marks a test function for skipping. + + This is a decorator factory that returns a decorator that will cause + tests to be skipped. + + Parameters + ---------- + msg : str + Optional message to be added. + + Returns + ------- + decorator : function + Decorator, which, when applied to a function, sets the skip + attribute of the function causing `twisted.trial` to skip it. + """ + + return skipif(True,msg) + + +def numpy_not_available(): + """Can numpy be imported? Returns true if numpy does NOT import. + + This is used to make a decorator to skip tests that require numpy to be + available, but delay the 'import numpy' to test execution time. + """ + try: + import numpy + np_not_avail = False + except ImportError: + np_not_avail = True + + return np_not_avail + +#----------------------------------------------------------------------------- +# Decorators for public use +#----------------------------------------------------------------------------- + +# 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 OS X") + +# Decorators to skip tests if not on specific platforms. +skip_if_not_win32 = skipif(sys.platform != 'win32', + "This test only runs under Windows") +skip_if_not_linux = skipif(sys.platform != 'linux2', + "This test only runs under Linux") +skip_if_not_osx = skipif(sys.platform != 'darwin', + "This test only runs under OSX") + +# Other skip decorators +skipif_not_numpy = skipif(numpy_not_available,"This test requires numpy") + +skipknownfailure = skip('This test is known to fail') + + diff --git a/IPython/testing/tests/test_decorators.py b/IPython/testing/tests/test_decorators.py index e91ec73..5f7e688 100644 --- a/IPython/testing/tests/test_decorators.py +++ b/IPython/testing/tests/test_decorators.py @@ -46,7 +46,7 @@ def test_deliberately_broken(): """A deliberately broken test - we want to skip this one.""" 1/0 -@dec.skip('foo') +@dec.skip('Testing the skip decorator') def test_deliberately_broken2(): """Another deliberately broken test - we want to skip this one.""" 1/0 diff --git a/IPython/testing/tests/test_decorators_trial.py b/IPython/testing/tests/test_decorators_trial.py new file mode 100644 index 0000000..6462285 --- /dev/null +++ b/IPython/testing/tests/test_decorators_trial.py @@ -0,0 +1,52 @@ +# encoding: utf-8 +""" +Tests for decorators_trial.py +""" + +#----------------------------------------------------------------------------- +# Copyright (C) 2008-2009 The IPython Development Team +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#----------------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# Imports +#----------------------------------------------------------------------------- + +# Tell nose to skip this module +__test__ = {} + +import os +import sys + +from twisted.trial import unittest +import IPython.testing.decorators_trial as dec + +#----------------------------------------------------------------------------- +# Tests +#----------------------------------------------------------------------------- + +class TestDecoratorsTrial(unittest.TestCase): + + @dec.skip() + def test_deliberately_broken(self): + """A deliberately broken test - we want to skip this one.""" + 1/0 + + @dec.skip('Testing the skip decorator') + def test_deliberately_broken2(self): + """Another deliberately broken test - we want to skip this one.""" + 1/0 + + @dec.skip_linux + def test_linux(self): + self.assertNotEquals(sys.platform,'linux2',"This test can't run under linux") + + @dec.skip_win32 + def test_win32(self): + self.assertNotEquals(sys.platform,'win32',"This test can't run under windows") + + @dec.skip_osx + def test_osx(self): + self.assertNotEquals(sys.platform,'darwin',"This test can't run under osx") \ No newline at end of file