Skip to content

Commit 21999d1

Browse files
committed
Merge pull request #349 from frishberg/run-on-failure-flag
Run on failure keyword only once.
2 parents aec5155 + 2025650 commit 21999d1

File tree

6 files changed

+55
-4
lines changed

6 files changed

+55
-4
lines changed

src/Selenium2Library/keywords/keywordgroup.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,22 @@
88
decorator = None # decorator module doesn't work with IronPython 2.6
99

1010
def _run_on_failure_decorator(method, *args, **kwargs):
11+
self = args[0]
12+
already_in_keyword = getattr(self, "_already_in_keyword", False) # If False, we are in the outermost keyword (or in `run_keyword`, if it's a dynamic library)
13+
self._already_in_keyword = True # Set a flag on the instance so that as we call keywords inside this call and this gets run again, we know we're at least one level in.
1114
try:
1215
return method(*args, **kwargs)
1316
except Exception, err:
14-
self = args[0]
15-
if hasattr(self, '_run_on_failure'):
17+
if hasattr(self, '_run_on_failure') and not self._has_run_on_failure:
18+
# If we're in an inner keyword, track the fact that we've already run on failure once
19+
self._has_run_on_failure = True
1620
self._run_on_failure()
1721
raise
22+
finally:
23+
if not already_in_keyword:
24+
# If we are in the outer call, reset the flags.
25+
self._already_in_keyword = False
26+
self._has_run_on_failure = False
1827

1928
class KeywordGroupMetaClass(type):
2029
def __new__(cls, clsname, bases, dict):

test/acceptance/keywords/run_on_failure.txt

100644100755
Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,37 @@
11
*** Settings ***
22
Suite Setup Run Keywords Go To Front Page Set Info Loglevel
33
Suite Teardown Set Debug Loglevel
4-
Test Teardown Register Keyword to Run on Failure Nothing
54
Resource ../resource.txt
65

76
*** Variables ***
87
${PAGE TITLE} (root)/index.html
98
${FAILURE MESSAGE} Page should not have contained text 'needle'
9+
${old order}
10+
11+
*** Keywords ***
12+
On Fail
13+
${count}= Evaluate ${ON FAIL COUNT} + 1
14+
Set Test Variable ${ON FAIL COUNT} ${count}
15+
16+
Prefer Custom Keywords
17+
Import Library CustomSeleniumKeywords
18+
${old order}= Set Library Search Order CustomSeleniumKeywords
19+
20+
Restore Old Search Order
21+
Set Library Search Order ${old order}
22+
23+
Open Browser To Front Page
24+
Open Browser ${FRONT PAGE}
1025

1126
*** Test Cases ***
27+
Run On Failure Keyword Only Called Once
28+
[Setup] Prefer Custom Keywords
29+
Set Test Variable ${ON FAIL COUNT} ${0}
30+
Register Keyword To Run On Failure On Fail
31+
Run Keyword And Ignore Error Custom Selenium Keyword
32+
Should Be Equal ${ON FAIL COUNT} ${1} On Failure Keyword called ${ON FAIL COUNT} times.
33+
[Teardown] Register Keyword to Run On Failure Nothing
34+
1235
Log Title On Failure
1336
[Documentation] LOG 1 Log Title will be run on failure. LOG 2:2 NONE LOG 3.1.1:1 ${PAGE TITLE} LOG 3.1:3 NONE
1437
Register Keyword to Run on Failure Log Title

test/acceptance/resource.txt

100644100755
File mode changed.

test/env.py

100644100755
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
ACCEPTANCE_TEST_DIR = os.path.join(ROOT_DIR, "acceptance")
77
LIB_DIR = os.path.join(ROOT_DIR, "lib")
88
RESOURCES_DIR = os.path.join(ROOT_DIR, "resources")
9+
TEST_LIBS_DIR = os.path.join(RESOURCES_DIR, "testlibs")
910
RESULTS_DIR = os.path.join(ROOT_DIR, "results")
1011
HTTP_SERVER_FILE = os.path.join(RESOURCES_DIR, 'testserver', 'testserver.py')
1112
SRC_DIR = os.path.join(ROOT_DIR, "..", "src")
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from Selenium2Library import Selenium2Library
2+
from robot.utils import asserts
3+
from robot.libraries.BuiltIn import BuiltIn
4+
5+
class CustomSeleniumKeywords(Selenium2Library):
6+
7+
def __init__(self, *args, **kwargs):
8+
"""Share `Selenium2Library`'s cache of browsers, so that
9+
we don't have to open a separate browser instance for the
10+
`Run On Failure Keyword Only Called Once` test."""
11+
ret = super(CustomSeleniumKeywords, self).__init__(*args, **kwargs)
12+
self._cache = BuiltIn().get_library_instance("Selenium2Library")._cache
13+
14+
def custom_selenium_keyword(self):
15+
self.custom_selenium_keyword_inner()
16+
17+
def custom_selenium_keyword_inner(self):
18+
asserts.assert_false(True)

test/run_tests.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
'--noncritical', 'known_issue_-_%(pyVersion)s',
3232
'--noncritical', 'known_issue_-_%(browser)s',
3333
]
34-
ARG_VALUES = {'outdir': env.RESULTS_DIR, 'pythonpath': env.SRC_DIR}
34+
ARG_VALUES = {'outdir': env.RESULTS_DIR, 'pythonpath': ':'.join((env.SRC_DIR, env.TEST_LIBS_DIR))}
3535

3636
def acceptance_tests(interpreter, browser, args):
3737
ARG_VALUES['browser'] = browser.replace('*', '')

0 commit comments

Comments
 (0)