summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrien Di Mascio <adim@logilab.fr>2006-05-18 09:15:37 +0200
committerAdrien Di Mascio <adim@logilab.fr>2006-05-18 09:15:37 +0200
commit2c01bbd132fd7f74c247519c75998d40dccaadc8 (patch)
treef75261855b90cfc9cbf63e52e79842e0b243b8bf
parent8121df79e137d72552b7b7825a3c68333035b1bc (diff)
downloadlogilab-common-2c01bbd132fd7f74c247519c75998d40dccaadc8.tar.gz
improved a bit generative test support and added tests for that
-rw-r--r--test/unittest_db.py4
-rw-r--r--test/unittest_table.py20
-rw-r--r--test/unittest_testlib.py100
-rw-r--r--testlib.py52
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()
diff --git a/testlib.py b/testlib.py
index 0a3a8fd..b3f377f 100644
--- a/testlib.py
+++ b/testlib.py
@@ -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