2 new revisions:

Revision: 7b737777349a
Author:   Janne Härkönen <[email protected]>
Date:     Fri May  6 06:28:25 2011
Log:      keyword teardown: handle execution errors better...
http://code.google.com/p/robotframework/source/detail?r=7b737777349a

Revision: 637dec02dd10
Author:   Janne Härkönen <[email protected]>
Date:     Fri May  6 06:28:59 2011
Log:      tests for keyword teardown
http://code.google.com/p/robotframework/source/detail?r=637dec02dd10

==============================================================================
Revision: 7b737777349a
Author:   Janne Härkönen <[email protected]>
Date:     Fri May  6 06:28:25 2011
Log:      keyword teardown: handle execution errors better

We need to take into account that the already happened
execution errors may have contunuable or other flags configured
when generating the final error from user keyword

Update issue 711
http://code.google.com/p/robotframework/source/detail?r=7b737777349a

Modified:
 /src/robot/errors.py
 /src/robot/running/context.py
 /src/robot/running/runerrors.py
 /src/robot/running/userkeyword.py

=======================================
--- /src/robot/errors.py        Sun Feb  6 01:24:10 2011
+++ /src/robot/errors.py        Fri May  6 06:28:25 2011
@@ -72,7 +72,7 @@
 class ExecutionFailed(RobotError):
     """Used for communicating failures in test execution."""

-    def __init__(self, message, timeout=False, syntax=False, exit=False,
+    def __init__(self, message, timeout=False, syntax=False, exit=False,
                  cont=False, exit_for_loop=False):
         RobotError.__init__(self, utils.cut_long_message(message))
         self.timeout = timeout
@@ -121,7 +121,8 @@
 class ExecutionFailures(ExecutionFailed):

     def __init__(self, errors):
-        ExecutionFailed.__init__(self, self._format_message(errors),
+        msg = self._format_message(*(unicode(e) for e in errors))
+        ExecutionFailed.__init__(self, msg,
                                  any(err.timeout for err in errors),
                                  any(err.syntax for err in errors),
                                  any(err.exit for err in errors),
@@ -129,17 +130,35 @@
                                  all(err.exit_for_loop for err in errors))
         self._errors = errors

-    def _format_message(self, errors):
-        if len(errors) == 1:
-            return unicode(errors[0])
+    def _format_message(self, *msgs):
+        if len(msgs) == 1:
+            return msgs[0]
         lines = ['Several failures occurred:'] \
- + ['%d) %s' % (i+1, unicode(e)) for i, e in enumerate(errors)]
+                + ['%d) %s' % (i+1, m) for i, m in enumerate(msgs)]
         return '\n\n'.join(lines)

     def get_errors(self):
         return self._errors


+class UserKeywordExecutionFailed(ExecutionFailures):
+
+    def __init__(self, run_error, teardown_error):
+        no_error = ExecutionFailed('', cont=True, exit_for_loop=True)
+        errors = (run_error or no_error,
+                  teardown_error or no_error)
+        ExecutionFailures.__init__(self, errors)
+        self._errors = run_error.get_errors() if \
+        (run_error and not teardown_error) else [self]
+
+    def _format_message(self, run_msg, td_msg):
+        if not td_msg:
+            return run_msg
+        if not run_msg:
+            return 'Keyword teardown failed:\n%s' % td_msg
+ return '%s\n\nAlso keyword teardown failed:\n%s' % (run_msg, td_msg)
+
+
 class RemoteError(RobotError):
     """Used by Remote library to report remote errors."""

=======================================
--- /src/robot/running/context.py       Fri May  6 04:52:43 2011
+++ /src/robot/running/context.py       Fri May  6 06:28:25 2011
@@ -21,7 +21,7 @@
         self.namespace = namespace
         self.output = output
         self.dry_run = dry_run
-        self._in_teardown = False
+        self._in_teardown = 0

     @property
     def teardown(self):
@@ -32,10 +32,10 @@
         return test_or_suite.status != 'RUNNING'

     def start_teardown(self):
-        self._in_teardown = True
+        self._in_teardown += 1

     def end_teardown(self):
-        self._in_teardown = False
+        self._in_teardown -= 1

     def get_current_vars(self):
         return self.namespace.variables
=======================================
--- /src/robot/running/runerrors.py     Fri May  6 04:52:43 2011
+++ /src/robot/running/runerrors.py     Fri May  6 06:28:25 2011
@@ -168,8 +168,7 @@
 class KeywordRunErrors(object):

     def __init__(self):
-        self._kw_err = ''
-        self._teardown_err = ''
+        self.teardown_error = None

     def get_message(self):
         if not self._teardown_err:
@@ -179,8 +178,8 @@
         return '%s\n\nAlso keyword teardown failed:\n%s' % (self._kw_err,
self._teardown_err)

-    def kw_err(self, error):
-        self._kw_err = unicode(error)
+

     def teardown_err(self, err):
-        self._teardown_err = unicode(err)
+        self.teardown_error = err
+
=======================================
--- /src/robot/running/userkeyword.py   Fri May  6 04:52:43 2011
+++ /src/robot/running/userkeyword.py   Fri May  6 06:28:25 2011
@@ -16,7 +16,7 @@
 import re

 from robot.common import BaseLibrary, UserErrorHandler
-from robot.errors import DataError, ExecutionFailed
+from robot.errors import DataError, ExecutionFailed, UserKeywordExecutionFailed
 from robot.variables import is_list_var, VariableSplitter
 from robot import utils

@@ -149,22 +149,26 @@
args_spec.set_variables(resolved_arguments, variables, context.output)
         self._verify_keyword_is_valid()
         self.timeout.start()
-        run_errors = KeywordRunErrors()
         try:
             self.keywords.run(context)
-        except ExecutionFailed, err:
-            run_errors.kw_err(err)
-        self._run_teardown(context, run_errors)
-        msg = run_errors.get_message()
-        if msg:
-            raise ExecutionFailed(msg)
-
-    def _run_teardown(self, context, run_errors):
+        except ExecutionFailed, error:
+            pass
+        else:
+            error = None
+        td_error = self._run_teardown(context)
+        if error or td_error:
+            raise UserKeywordExecutionFailed(error, td_error)
+
+    def _run_teardown(self, context):
+        if not self.teardown:
+            return
         teardown = Teardown(self.teardown.name, self.teardown.args)
         teardown.replace_variables(context.get_current_vars(), [])
         context.start_teardown()
+        run_errors = KeywordRunErrors()
         teardown.run(context, KeywordTeardownListener(run_errors))
         context.end_teardown()
+        return run_errors.teardown_error

     def _verify_keyword_is_valid(self):
         if self._errors:
@@ -226,9 +230,11 @@
             raise TypeError('Does not match given name')
         self.embedded_args = zip(template.embedded_args, match.groups())
         self.name = name
+        self.teardown = None
         self.origname = template.name
         self._copy_attrs_from_template(template)

+
     def run(self, context, args):
         for name, value in self.embedded_args:
context.get_current_vars()[name] = context.get_current_vars().replace_scalar(value)

==============================================================================
Revision: 637dec02dd10
Author:   Janne Härkönen <[email protected]>
Date:     Fri May  6 06:28:59 2011
Log:      tests for keyword teardown
http://code.google.com/p/robotframework/source/detail?r=637dec02dd10

Added:
 /atest/robot/core/keyword_teardown.txt
 /atest/testdata/core/keyword_teardown.txt

=======================================
--- /dev/null
+++ /atest/robot/core/keyword_teardown.txt      Fri May  6 06:28:59 2011
@@ -0,0 +1,55 @@
+*** Settings ***
+Resource     atest_resource.txt
+Force Tags   regression  pybot  jybot
+Suite Setup  Run Tests  ${EMPTY}  core/keyword_teardown.txt
+
+*** Test Cases ***
+Passing Keyword with Teardown
+    ${tc}=  Check Test Case  ${TESTNAME}
+    Check Log Message  ${tc.kws[0].kws[0].msgs[0]}  In UK
+    Check Log Message  ${tc.kws[0].kws[1].msgs[0]}  In UK Teardown
+
+Failing Keyword with Teardown
+    ${tc}=  Check Test Case  ${TESTNAME}
+    Check Log Message  ${tc.kws[0].kws[0].msgs[0]}  Expected Failure!  FAIL
+    Check Log Message  ${tc.kws[0].kws[1].msgs[0]}  In Failing UK Teardown
+
+Failure in Keyword Teardown
+    ${tc}=  Check Test Case  ${TESTNAME}
+    Check Log Message  ${tc.kws[0].kws[0].msgs[0]}  In UK
+ Check Log Message ${tc.kws[0].kws[1].msgs[0]} Failing in UK Teardown FAIL
+
+Failures in Keyword and Teardown
+    ${tc}=  Check Test Case  ${TESTNAME}
+    Check Log Message  ${tc.kws[0].kws[0].msgs[0]}  Expected Failure!  FAIL
+ Check Log Message ${tc.kws[0].kws[1].msgs[0]} Failing in UK Teardown FAIL
+
+Multiple Failures in Keyword Teardown
+    ${tc}=  Check Test Case  ${TESTNAME}
+ Check Log Message ${tc.kws[0].kws[1].kws[0].msgs[0]} Failure in Teardown FAIL + Check Log Message ${tc.kws[0].kws[1].kws[1].kws[0].msgs[0]} Expected Failure! FAIL + Check Log Message ${tc.kws[0].kws[1].kws[1].kws[1].msgs[0]} Executed if in nested Teardown + Check Log Message ${tc.kws[0].kws[1].kws[2].msgs[0]} Third failure in Teardown FAIL
+
+Nested Keyword Teardowns
+    ${tc}=  Check Test Case  ${TESTNAME}
+    Check Log Message  ${tc.kws[0].kws[0].kws[0].msgs[0]}  In UK
+    Check Log Message  ${tc.kws[0].kws[0].kws[1].msgs[0]}  In UK Teardown
+    Check Log Message  ${tc.kws[0].kws[1].kws[0].msgs[0]}  In UK
+    Check Log Message  ${tc.kws[0].kws[1].kws[1].msgs[0]}  In UK Teardown
+
+Nested Keyword Teardown Failures
+    ${tc}=  Check Test Case  ${TESTNAME}
+ Check Log Message ${tc.kws[0].kws[0].kws[1].msgs[0]} Failing in UK Teardown FAIL + Check Log Message ${tc.kws[0].kws[1].msgs[0]} Failing in outer UK Teardown FAIL
+
+Continuable Failure in Keyword
+    ${tc}=  Check Test Case  ${TESTNAME}
+ Check Log Message ${tc.kws[0].kws[0].kws[0].msgs[0]} Please continue FAIL + Check Log Message ${tc.kws[0].kws[1].msgs[0]} After continuable failure
+    Check Log Message  ${tc.kws[0].kws[2].msgs[0]}  In UK Teardown
+
+Replacing Variables in Keyword Teardown Fails
+    Check Test Case  ${TESTNAME}
+
+
=======================================
--- /dev/null
+++ /atest/testdata/core/keyword_teardown.txt   Fri May  6 06:28:59 2011
@@ -0,0 +1,81 @@
+*** Test Cases ***
+
+Passing Keyword with Teardown
+    Keyword with Teardown
+
+Failing Keyword with Teardown
+    [Documentation]  FAIL Expected Failure!
+    Failing Keyword with Teardown
+
+Failure in Keyword Teardown
+    [Documentation]  FAIL Keyword teardown failed:\nFailing in UK Teardown
+    Failure in Keyword Teardown
+    Fail  This should never be run
+
+Failures in Keyword and Teardown
+ [Documentation] FAIL Expected Failure!\n\nAlso keyword teardown failed:\nFailing in UK Teardown
+    Failures in Keyword and Teardown
+
+Multiple Failures in Keyword Teardown
+ [Documentation] FAIL Keyword teardown failed:\nSeveral failures occurred:\n\n1) Failure in Teardown\n\n2) Expected Failure!\n\n3) Third failure in Teardown
+    Multiple Failures in Keyword Teardown
+
+Nested Keyword Teardowns
+    Nested Keyword Teardowns
+
+Nested Keyword Teardown Failures
+ [Documentation] FAIL Keyword teardown failed:\nFailing in UK Teardown\n\nAlso keyword teardown failed:\nFailing in outer UK Teardown
+    Nested Keyword Teardown Failures
+
+Continuable Failure in Keyword
+    [Documentation]  FAIL Please continue
+    Continuable Failure in Keyword
+
+Replacing Variables in Keyword Teardown Fails
+ [Documentation] FAIL Keyword teardown failed:\nNo keyword with name '${NON EXISTING}' found.
+    Replacing Variables in Keyword Teardown Fails
+
+
+*** Keywords ***
+Keyword with Teardown
+    Log  In UK
+    [Teardown]  Log  In UK Teardown
+
+Failing Keyword with Teardown
+    Fail  Expected Failure!
+    Log   Executed if in nested Teardown
+    [Teardown]  Log  In Failing UK Teardown
+
+Failure in Keyword Teardown
+    Log  In UK
+    [Teardown]  Fail  Failing in UK Teardown
+
+Failures in Keyword and Teardown
+    Fail  Expected Failure!
+    [Teardown]  Fail  Failing in UK Teardown
+
+Nested Keyword Teardowns
+    Keyword with Teardown
+    [Teardown]  Keyword with Teardown
+
+Nested Keyword Teardown Failures
+    Failure in Keyword Teardown
+    [Teardown]  Fail  Failing in outer UK Teardown
+
+Continuable Failure in Keyword
+    Run Keyword and Continue on Failure  Fail  Please continue
+    Log  After continuable failure
+    [Teardown]  Log  In UK Teardown
+
+Multiple Failures in Keyword Teardown
+    Log  In UK
+    [Teardown]  Multiple Failures
+
+Multiple Failures
+    Fail  Failure in Teardown
+    Failing keyword with Teardown
+    Fail  Third failure in Teardown
+
+Replacing Variables in Keyword Teardown Fails
+    Log  In UK
+    [Teardown]  ${NON EXISTING}

Reply via email to