From 4cb49b631b9e1cf21db3f373e3ee2e6963155efa Mon Sep 17 00:00:00 2001 From: Adrien Di Mascio Date: Sun, 21 May 2006 22:37:23 +0200 Subject: attempt to support keyword args and var args in generative tests --- test/unittest_testlib.py | 1 + testlib.py | 47 +++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/test/unittest_testlib.py b/test/unittest_testlib.py index 45488b1..4bda665 100644 --- a/test/unittest_testlib.py +++ b/test/unittest_testlib.py @@ -131,6 +131,7 @@ class TestlibTC(TestCase): self.assertRaises(AssertionError, self.tc.assertTextEqual, text1, text2) + class GenerativeTestsTC(TestCase): def setUp(self): diff --git a/testlib.py b/testlib.py index b3f377f..acbd943 100644 --- a/testlib.py +++ b/testlib.py @@ -351,6 +351,15 @@ class SkipAwareTextTestRunner(unittest.TextTestRunner): self.verbosity, self.exitfirst) +class keywords(dict): + """keyword args (**kwargs) support for generative tests""" + +class starargs(tuple): + """variable arguments (*args) for generative tests""" + def __new__(cls, *args): + return tuple.__new__(cls, args) + + class SkipAwareTestProgram(unittest.TestProgram): # XXX: don't try to stay close to unittest.py, use optparse USAGE = """\ @@ -412,17 +421,42 @@ Examples: sys.exit(not result.wasSuccessful()) def unittest_main(): - """use this functon if you want to have the same functionality as unittest.main""" + """use this functon if you want to have the same functionality + as unittest.main""" SkipAwareTestProgram() class TestSkipped(Exception): """raised when a test is skipped""" - def is_generator(function): flags = function.func_code.co_flags return flags & CO_GENERATOR + +def parse_generative_args(params): + args = [] + varargs = () + kwargs = {} + flags = 0 # 2 <=> starargs, 4 <=> kwargs + for param in params: + if isinstance(param, starargs): + varargs = param + if flags: + raise TypeError('found starargs after keywords !') + flags |= 2 + args += list(varargs) + elif isinstance(param, keywords): + kwargs = param + if flags & 4: + raise TypeError('got multiple keywords parameters') + flags |= 4 + elif flags & 2 or flags & 4: + raise TypeError('found parameters after kwargs or args') + else: + args.append(param) + + return args, kwargs + class TestCase(unittest.TestCase): """unittest.TestCase with some additional methods""" @@ -465,10 +499,10 @@ class TestCase(unittest.TestCase): try: for params in testfunc(): func = params[0] - args = params[1:] + args, kwargs = parse_generative_args(params[1:]) # increment test counter manually result.testsRun += 1 - success = self._proceed(result, func, args, stop_on_error=True) + success = self._proceed(result, func, args, kwargs, stop_on_error=True) # XXX: how should tearDown errors be handled here ? if success: result.addSuccess(self) @@ -480,12 +514,13 @@ class TestCase(unittest.TestCase): success = False return success - def _proceed(self, result, testfunc, args=(), stop_on_error=False): + def _proceed(self, result, testfunc, args=(), kwargs=None, stop_on_error=False): """proceed the actual test returns True on sucess, False on error or failure """ + kwargs = kwargs or {} try: - testfunc(*args) + testfunc(*args, **kwargs) except self.failureException: result.addFailure(self, self.__exc_info()) return False -- cgit v1.2.1