diff options
author | Adrien Di Mascio <adim@logilab.fr> | 2006-05-18 09:15:37 +0200 |
---|---|---|
committer | Adrien Di Mascio <adim@logilab.fr> | 2006-05-18 09:15:37 +0200 |
commit | 2c01bbd132fd7f74c247519c75998d40dccaadc8 (patch) | |
tree | f75261855b90cfc9cbf63e52e79842e0b243b8bf | |
parent | 8121df79e137d72552b7b7825a3c68333035b1bc (diff) | |
download | logilab-common-2c01bbd132fd7f74c247519c75998d40dccaadc8.tar.gz |
improved a bit generative test support and added tests for that
-rw-r--r-- | test/unittest_db.py | 4 | ||||
-rw-r--r-- | test/unittest_table.py | 20 | ||||
-rw-r--r-- | test/unittest_testlib.py | 100 | ||||
-rw-r--r-- | testlib.py | 52 |
4 files changed, 139 insertions, 37 deletions
diff --git a/test/unittest_db.py b/test/unittest_db.py index b7e04f7..8049220 100644 --- a/test/unittest_db.py +++ b/test/unittest_db.py @@ -154,8 +154,8 @@ class DBAPIAdaptersTC(TestCase): 'int8', 'float4', 'float8', 'numeric', 'bool', 'money') for num_type in number_types: - self.assertEquals(num_type, module.NUMBER) - self.assertNotEquals('char', module.NUMBER) + yield self.assertEquals, num_type, module.NUMBER + yield self.assertNotEquals, 'char', module.NUMBER def test_pypgsql_getattr(self): """Tests the getattr() delegation for pyPgSQL""" diff --git a/test/unittest_table.py b/test/unittest_table.py index 5fc4be3..f9e955a 100644 --- a/test/unittest_table.py +++ b/test/unittest_table.py @@ -4,14 +4,15 @@ Unittests for table management __revision__ = '$Id: unittest_table.py,v 1.13 2006-04-09 22:30:53 nico Exp $' -import unittest import sys +from cStringIO import StringIO + +from logilab.common.testib import TestCase, unittest_main from logilab.common.table import Table, TableStyleSheet, DocbookTableWriter, \ DocbookRenderer, TableStyle, TableWriter, TableCellRenderer from logilab.common.compat import set -from cStringIO import StringIO -class TableTC(unittest.TestCase): +class TableTC(TestCase): """Table TestCase class""" def setUp(self): @@ -190,7 +191,7 @@ class TableTC(unittest.TestCase): str(self.table) -class GroupByTC(unittest.TestCase): +class GroupByTC(TestCase): """specific test suite for groupby()""" def setUp(self): t = Table() @@ -244,7 +245,7 @@ class GroupByTC(unittest.TestCase): ('date1', 'ing1', 'task3', 0.3), ]) -class TableStyleSheetTC(unittest.TestCase): +class TableStyleSheetTC(TestCase): """The Stylesheet test case """ def setUp(self): @@ -326,7 +327,7 @@ class TableStyleSheetTC(unittest.TestCase): -class TableStyleTC(unittest.TestCase): +class TableStyleTC(TestCase): """Test suite for TableSuite""" def setUp(self): self.table = Table() @@ -364,7 +365,7 @@ class TableStyleTC(unittest.TestCase): self.assertEquals(igetter(1), 'FOO') -class RendererTC(unittest.TestCase): +class RendererTC(TestCase): """Test suite for DocbookRenderer""" def setUp(self): self.renderer = DocbookRenderer(alignment = True) @@ -403,8 +404,7 @@ class RendererTC(unittest.TestCase): self.assertEquals(cell_content, '12 EUR') -from logilab.common import testlib -class DocbookTableWriterTC(testlib.TestCase): +class DocbookTableWriterTC(TestCase): """TestCase for table's writer""" def setUp(self): self.stream = StringIO() @@ -425,4 +425,4 @@ class DocbookTableWriterTC(testlib.TestCase): if __name__ == '__main__': - testlib.unittest_main() + unittest_main() diff --git a/test/unittest_testlib.py b/test/unittest_testlib.py index a4b68a7..45488b1 100644 --- a/test/unittest_testlib.py +++ b/test/unittest_testlib.py @@ -4,15 +4,18 @@ __revision__ = '$Id: unittest_testlib.py,v 1.5 2006-02-09 22:37:46 nico Exp $' import unittest from os.path import join, dirname +from cStringIO import StringIO + try: __file__ except NameError: import sys __file__ = sys.argv[0] -from logilab.common import testlib +from logilab.common.testlib import TestCase, unittest_main, SkipAwareTextTestRunner +from logilab.common.testlib import mock_object -class MockTestCase(testlib.TestCase): +class MockTestCase(TestCase): def __init__(self): # Do not call unittest.TestCase's __init__ pass @@ -20,14 +23,14 @@ class MockTestCase(testlib.TestCase): def fail(self, msg): raise AssertionError(msg) -class UtilTC(testlib.TestCase): +class UtilTC(TestCase): def test_mockobject(self): - obj = testlib.mock_object(foo='bar', baz='bam') + obj = mock_object(foo='bar', baz='bam') self.assertEquals(obj.foo, 'bar') self.assertEquals(obj.baz, 'bam') -class TestlibTC(testlib.TestCase): +class TestlibTC(TestCase): def setUp(self): self.tc = MockTestCase() @@ -126,7 +129,92 @@ class TestlibTC(testlib.TestCase): self.tc.assertTextEqual(text1, text1) text2 = file(spam).read() self.assertRaises(AssertionError, self.tc.assertTextEqual, text1, text2) + + +class GenerativeTestsTC(TestCase): + + def setUp(self): + output = StringIO() + self.runner = SkipAwareTextTestRunner(stream=output) + + def test_generative_ok(self): + class FooTC(TestCase): + def test_generative(self): + for i in xrange(10): + yield self.assertEquals, i, i + result = self.runner.run(FooTC('test_generative')) + self.assertEquals(result.testsRun, 10) + self.assertEquals(len(result.failures), 0) + self.assertEquals(len(result.errors), 0) + + + def test_generative_half_bad(self): + class FooTC(TestCase): + def test_generative(self): + for i in xrange(10): + yield self.assertEquals, i%2, 0 + result = self.runner.run(FooTC('test_generative')) + self.assertEquals(result.testsRun, 10) + self.assertEquals(len(result.failures), 5) + self.assertEquals(len(result.errors), 0) + + + def test_generative_error(self): + class FooTC(TestCase): + def test_generative(self): + for i in xrange(10): + if i == 5: + raise ValueError('STOP !') + yield self.assertEquals, i, i + + result = self.runner.run(FooTC('test_generative')) + self.assertEquals(result.testsRun, 5) + self.assertEquals(len(result.failures), 0) + self.assertEquals(len(result.errors), 1) + + + def test_generative_setup(self): + class FooTC(TestCase): + def setUp(self): + raise ValueError('STOP !') + def test_generative(self): + for i in xrange(10): + yield self.assertEquals, i, i + + result = self.runner.run(FooTC('test_generative')) + self.assertEquals(result.testsRun, 1) + self.assertEquals(len(result.failures), 0) + self.assertEquals(len(result.errors), 1) + + +class ExitFirstTC(TestCase): + def setUp(self): + output = StringIO() + self.runner = SkipAwareTextTestRunner(stream=output, exitfirst=True) + + def test_simple_exit_first(self): + class FooTC(TestCase): + def test_1(self): + assert False + def test_2(self): + assert False + tests = [FooTC('test_1'), FooTC('test_2')] + result = self.runner.run(unittest.TestSuite(tests)) + self.assertEquals(result.testsRun, 1) + self.assertEquals(len(result.failures), 1) + self.assertEquals(len(result.errors), 0) + + def test_generative_exit_first(self): + class FooTC(TestCase): + def test_generative(self): + for i in xrange(10): + yield self.assert_, False + result = self.runner.run(FooTC('test_generative')) + self.assertEquals(result.testsRun, 1) + self.assertEquals(len(result.failures), 1) + self.assertEquals(len(result.errors), 0) + if __name__ == '__main__': - testlib.unittest_main() + unittest_main() @@ -342,8 +342,8 @@ class SkipAwareTestResult(unittest._TextTestResult): class SkipAwareTextTestRunner(unittest.TextTestRunner): - def __init__(self, verbosity=1, exitfirst=False): - unittest.TextTestRunner.__init__(self, verbosity=verbosity) + def __init__(self, stream=sys.stderr, verbosity=1, exitfirst=False): + unittest.TextTestRunner.__init__(self, stream=stream, verbosity=verbosity) self.exitfirst = exitfirst def _makeResult(self): @@ -427,7 +427,10 @@ class TestCase(unittest.TestCase): """unittest.TestCase with some additional methods""" def __call__(self, result=None): - """rewrite TestCase.__call__ to support generative tests""" + """rewrite TestCase.__call__ to support generative tests + This is mostly a copy/paste from unittest.py (i.e same + variable names, same logic, except for the generative tests part) + """ if result is None: result = self.defaultTestResult() result.startTest(self) testMethod = getattr(self, self.__testMethodName) @@ -441,18 +444,7 @@ class TestCase(unittest.TestCase): return # generative tests if is_generator(testMethod.im_func): - result.testsRun -= 1 - for params in testMethod(): - func = params[0] - args = params[1:] - # increment test counter manually - result.testsRun += 1 - success = self._proceed(result, func, args) - # XXX: how should tearDown errors be handled here ? - if success: - result.addSuccess(self) - elif result.shouldStop: - break + success = self._proceed_generative(result, testMethod) else: success = self._proceed(result, testMethod) try: @@ -467,7 +459,28 @@ class TestCase(unittest.TestCase): finally: result.stopTest(self) - def _proceed(self, result, testfunc, args=()): + def _proceed_generative(self, result, testfunc, args=()): + # cancel startTest()'s increment + result.testsRun -= 1 + try: + for params in testfunc(): + func = params[0] + args = params[1:] + # increment test counter manually + result.testsRun += 1 + success = self._proceed(result, func, args, stop_on_error=True) + # XXX: how should tearDown errors be handled here ? + if success: + result.addSuccess(self) + elif result.shouldStop: + break + except: + # if an error occurs between two yield + result.addError(self, self.__exc_info()) + success = False + return success + + def _proceed(self, result, testfunc, args=(), stop_on_error=False): """proceed the actual test returns True on sucess, False on error or failure """ @@ -478,11 +491,12 @@ class TestCase(unittest.TestCase): return False except KeyboardInterrupt: raise - except TestSkipped: - exc_type, exc, tcbk = self.__exc_info() - result.addSkipped(self, exc) +## except TestSkipped: +## exc_type, exc, tcbk = self.__exc_info() +## result.addSkipped(self, exc) except: result.addError(self, self.__exc_info()) + result.shouldStop = stop_on_error return False return True |