diff --git a/avocado/__init__.py b/avocado/__init__.py index 579eb95606a94577721db558b6e9840465e965f4..cd2dfe5b06738e94f232902b510a6258f066747c 100644 --- a/avocado/__init__.py +++ b/avocado/__init__.py @@ -13,10 +13,10 @@ # Author: Lucas Meneghel Rodrigues -__all__ = ['main', 'Test', 'VERSION', 'fail_on_error'] +__all__ = ['main', 'Test', 'VERSION', 'fail_on'] from avocado.core.job import main from avocado.core.test import Test from avocado.core.version import VERSION -from avocado.core.exceptions import fail_on_error +from avocado.core.exceptions import fail_on diff --git a/avocado/core/exceptions.py b/avocado/core/exceptions.py index 9035815acdd0d9af444e2a8f5afaf94eec764aa8..b3e2df5e1c214b9f8d156607a475f4fcb36494c7 100644 --- a/avocado/core/exceptions.py +++ b/avocado/core/exceptions.py @@ -15,29 +15,45 @@ """ Exception classes, useful for tests, and other parts of the framework code. """ - - -def fail_on_error(fn): - """ - Apply to any test you want to FAIL upon any exception raised. - - Normally only TestFail called explicitly will mark an avocado test with the - FAIL state, but this decorator is provided as a convenience for people - that need a more relaxed behavior. - - :param fn: Function that will be decorated - """ - def new_fn(*args, **kwargs): - try: - return fn(*args, **kwargs) - except TestBaseException: - raise - except Exception, e: - raise TestFail(str(e)) - new_fn.__name__ = fn.__name__ - new_fn.__doc__ = fn.__doc__ - new_fn.__dict__.update(fn.__dict__) - return new_fn +from functools import wraps +import types + + +def fail_on(exceptions=None): + """ + Fail the test when decorated function produces exception of the specified + type. + + (For example, our method may raise IndexError on tested software failure. + We can either try/catch it or use this decorator instead) + + :param exceptions: Tuple or single exception to be assumed as + test fail [Exception] + :note: self.error and self.skip behavior remains intact + :note: To allow simple usage param "exceptions" must not be callable + """ + func = False + if exceptions is None: + exceptions = Exception + elif isinstance(exceptions, types.FunctionType): # @fail_on without () + func = exceptions + exceptions = Exception + + def decorate(func): + """ Decorator """ + @wraps(func) + def wrap(*args, **kwargs): + """ Function wrapper """ + try: + return func(*args, **kwargs) + except TestBaseException: + raise + except exceptions, details: + raise TestFail(str(details)) + return wrap + if func: + return decorate(func) + return decorate class JobBaseException(Exception): diff --git a/examples/tests/fail_on_error.py b/examples/tests/fail_on_exception.py similarity index 74% rename from examples/tests/fail_on_error.py rename to examples/tests/fail_on_exception.py index 39c057872b04083de5787d9ebd5b98c1022b81a4..40a97459babbf9358d5d09019784545a4588c640 100755 --- a/examples/tests/fail_on_error.py +++ b/examples/tests/fail_on_exception.py @@ -3,13 +3,14 @@ import avocado -class FailOnError(avocado.Test): +class FailOnException(avocado.Test): """ - Test illustrating the behavior of the fail_on_error decorator. + Test illustrating the behavior of the fail_on decorator. """ - @avocado.fail_on_error + # @avocado.fail_on(ValueError) also possible + @avocado.fail_on def test(self): """ This should end with FAIL. diff --git a/selftests/all/functional/avocado/basic_tests.py b/selftests/all/functional/avocado/basic_tests.py index e666d7e46c5b5bb07f680a0fc5e93cbb1507d449..fb748b89e459496fc23d47f11dd9daca08d56664 100644 --- a/selftests/all/functional/avocado/basic_tests.py +++ b/selftests/all/functional/avocado/basic_tests.py @@ -126,10 +126,10 @@ class RunnerOperationTest(unittest.TestCase): result)) self.assertIn('"status": "ERROR"', result.stdout) - def test_fail_on_error(self): + def test_fail_on_exception(self): os.chdir(basedir) cmd_line = ("./scripts/avocado run --sysinfo=off --job-results-dir %s " - "--json - fail_on_error" % self.tmpdir) + "--json - fail_on_exception" % self.tmpdir) result = process.run(cmd_line, ignore_status=True) expected_rc = 1 self.assertEqual(result.exit_status, expected_rc,