Refactoring
This commit is contained in:
parent
dc6fb95b68
commit
3c260affd0
|
@ -10,6 +10,7 @@ from seleniumbase.fixtures import constants
|
||||||
python3_11_or_newer = False
|
python3_11_or_newer = False
|
||||||
if sys.version_info >= (3, 11):
|
if sys.version_info >= (3, 11):
|
||||||
python3_11_or_newer = True
|
python3_11_or_newer = True
|
||||||
|
py311_patch2 = constants.PatchPy311.PATCH
|
||||||
|
|
||||||
|
|
||||||
def log_screenshot(test_logpath, driver, screenshot=None, get=False):
|
def log_screenshot(test_logpath, driver, screenshot=None, get=False):
|
||||||
|
@ -79,7 +80,11 @@ def get_master_time():
|
||||||
|
|
||||||
|
|
||||||
def get_browser_version(driver):
|
def get_browser_version(driver):
|
||||||
if python3_11_or_newer and hasattr(sb_config, "_browser_version"):
|
if (
|
||||||
|
python3_11_or_newer
|
||||||
|
and py311_patch2
|
||||||
|
and hasattr(sb_config, "_browser_version")
|
||||||
|
):
|
||||||
return sb_config._browser_version
|
return sb_config._browser_version
|
||||||
driver_capabilities = driver.capabilities
|
driver_capabilities = driver.capabilities
|
||||||
if "version" in driver_capabilities:
|
if "version" in driver_capabilities:
|
||||||
|
@ -187,6 +192,25 @@ def log_test_failure_data(test, test_logpath, driver, browser, url=None):
|
||||||
traceback_list = traceback.format_list(
|
traceback_list = traceback.format_list(
|
||||||
traceback.extract_tb(traceback_address)[1:]
|
traceback.extract_tb(traceback_address)[1:]
|
||||||
)
|
)
|
||||||
|
updated_list = []
|
||||||
|
counter = 0
|
||||||
|
for traceback_item in traceback_list:
|
||||||
|
if "self._callTestMethod(testMethod)" in traceback_item:
|
||||||
|
counter = 1
|
||||||
|
updated_list.append(traceback_item) # In case not cleared
|
||||||
|
continue
|
||||||
|
elif (
|
||||||
|
", in _callTestMethod" in traceback_item.strip()
|
||||||
|
and "method()" in traceback_item.strip()
|
||||||
|
and counter == 1
|
||||||
|
):
|
||||||
|
counter = 0
|
||||||
|
updated_list = []
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
counter = 0
|
||||||
|
updated_list.append(traceback_item)
|
||||||
|
traceback_list = updated_list
|
||||||
traceback_message = "".join(traceback_list).strip()
|
traceback_message = "".join(traceback_list).strip()
|
||||||
except Exception:
|
except Exception:
|
||||||
exc_message = "(Unknown Exception)"
|
exc_message = "(Unknown Exception)"
|
||||||
|
@ -201,13 +225,17 @@ def log_test_failure_data(test, test_logpath, driver, browser, url=None):
|
||||||
if sb_config.behave_step.error_message:
|
if sb_config.behave_step.error_message:
|
||||||
traceback_message = sb_config.behave_step.error_message
|
traceback_message = sb_config.behave_step.error_message
|
||||||
else:
|
else:
|
||||||
traceback_message = "".join(
|
format_exception = traceback.format_exception(
|
||||||
traceback.format_exception(
|
sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]
|
||||||
sys.exc_info()[0],
|
|
||||||
sys.exc_info()[1],
|
|
||||||
sys.exc_info()[2],
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
if format_exception:
|
||||||
|
updated_list = []
|
||||||
|
for line in format_exception:
|
||||||
|
if "sb_manager.py" in line and "yield sb" in line:
|
||||||
|
continue
|
||||||
|
updated_list.append(line)
|
||||||
|
format_exception = updated_list
|
||||||
|
traceback_message = "".join(format_exception)
|
||||||
if (
|
if (
|
||||||
not traceback_message
|
not traceback_message
|
||||||
or len(str(traceback_message)) < 30
|
or len(str(traceback_message)) < 30
|
||||||
|
|
|
@ -77,6 +77,7 @@ from seleniumbase.fixtures import js_utils
|
||||||
from seleniumbase.fixtures import page_actions
|
from seleniumbase.fixtures import page_actions
|
||||||
from seleniumbase.fixtures import page_utils
|
from seleniumbase.fixtures import page_utils
|
||||||
from seleniumbase.fixtures import shared_utils
|
from seleniumbase.fixtures import shared_utils
|
||||||
|
from seleniumbase.fixtures import unittest_helper
|
||||||
from seleniumbase.fixtures import xpath_to_css
|
from seleniumbase.fixtures import xpath_to_css
|
||||||
|
|
||||||
__all__ = ["BaseCase"]
|
__all__ = ["BaseCase"]
|
||||||
|
@ -91,6 +92,7 @@ if sys.platform in ["win32", "win64", "x64"]:
|
||||||
python3_11_or_newer = False
|
python3_11_or_newer = False
|
||||||
if sys.version_info >= (3, 11):
|
if sys.version_info >= (3, 11):
|
||||||
python3_11_or_newer = True
|
python3_11_or_newer = True
|
||||||
|
py311_patch2 = constants.PatchPy311.PATCH
|
||||||
selenium4_or_newer = False
|
selenium4_or_newer = False
|
||||||
if sys.version_info >= (3, 7):
|
if sys.version_info >= (3, 7):
|
||||||
selenium4_or_newer = True
|
selenium4_or_newer = True
|
||||||
|
@ -307,7 +309,6 @@ class BaseCase(unittest.TestCase):
|
||||||
pass # Odd issue where the open did happen. Continue.
|
pass # Odd issue where the open did happen. Continue.
|
||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
unittest.has_exception = False
|
|
||||||
if (
|
if (
|
||||||
self.undetectable
|
self.undetectable
|
||||||
or (
|
or (
|
||||||
|
@ -4120,7 +4121,6 @@ class BaseCase(unittest.TestCase):
|
||||||
and settings.SKIP_JS_WAITS
|
and settings.SKIP_JS_WAITS
|
||||||
):
|
):
|
||||||
time.sleep(0.05)
|
time.sleep(0.05)
|
||||||
unittest.has_exception = False
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def wait_for_angularjs(self, timeout=None, **kwargs):
|
def wait_for_angularjs(self, timeout=None, **kwargs):
|
||||||
|
@ -6362,14 +6362,12 @@ class BaseCase(unittest.TestCase):
|
||||||
)
|
)
|
||||||
if type(page) is int:
|
if type(page) is int:
|
||||||
if text not in pdf_text:
|
if text not in pdf_text:
|
||||||
unittest.has_exception = True
|
|
||||||
raise Exception(
|
raise Exception(
|
||||||
"PDF [%s] is missing expected text [%s] on "
|
"PDF [%s] is missing expected text [%s] on "
|
||||||
"page [%s]!" % (pdf, text, page)
|
"page [%s]!" % (pdf, text, page)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
if text not in pdf_text:
|
if text not in pdf_text:
|
||||||
unittest.has_exception = True
|
|
||||||
raise Exception(
|
raise Exception(
|
||||||
"PDF [%s] is missing expected text [%s]!" % (pdf, text)
|
"PDF [%s] is missing expected text [%s]!" % (pdf, text)
|
||||||
)
|
)
|
||||||
|
@ -6495,7 +6493,19 @@ class BaseCase(unittest.TestCase):
|
||||||
from PIL import Image, ImageDraw
|
from PIL import Image, ImageDraw
|
||||||
except Exception:
|
except Exception:
|
||||||
shared_utils.pip_install("Pillow")
|
shared_utils.pip_install("Pillow")
|
||||||
from PIL import Image, ImageDraw
|
try:
|
||||||
|
from PIL import Image, ImageDraw
|
||||||
|
except Exception as e:
|
||||||
|
if (
|
||||||
|
sys.version_info >= (3, 12)
|
||||||
|
and "symbol not found" in e.msg
|
||||||
|
):
|
||||||
|
raise Exception(
|
||||||
|
"PIL / Pillow is not supported on Python %s"
|
||||||
|
% ".".join(str(s) for s in sys.version_info)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
raise
|
||||||
text_rows = overlay_text.split("\n")
|
text_rows = overlay_text.split("\n")
|
||||||
len_text_rows = len(text_rows)
|
len_text_rows = len(text_rows)
|
||||||
max_width = 0
|
max_width = 0
|
||||||
|
@ -6744,44 +6754,32 @@ class BaseCase(unittest.TestCase):
|
||||||
def assert_true(self, expr, msg=None):
|
def assert_true(self, expr, msg=None):
|
||||||
"""Asserts that the expression is True.
|
"""Asserts that the expression is True.
|
||||||
Will raise an exception if the statement if False."""
|
Will raise an exception if the statement if False."""
|
||||||
unittest.has_exception = True
|
|
||||||
self.assertTrue(expr, msg=msg)
|
self.assertTrue(expr, msg=msg)
|
||||||
unittest.has_exception = False
|
|
||||||
|
|
||||||
def assert_false(self, expr, msg=None):
|
def assert_false(self, expr, msg=None):
|
||||||
"""Asserts that the expression is False.
|
"""Asserts that the expression is False.
|
||||||
Will raise an exception if the statement if True."""
|
Will raise an exception if the statement if True."""
|
||||||
unittest.has_exception = True
|
|
||||||
self.assertFalse(expr, msg=msg)
|
self.assertFalse(expr, msg=msg)
|
||||||
unittest.has_exception = False
|
|
||||||
|
|
||||||
def assert_equal(self, first, second, msg=None):
|
def assert_equal(self, first, second, msg=None):
|
||||||
"""Asserts that the two values are equal.
|
"""Asserts that the two values are equal.
|
||||||
Will raise an exception if the values are not equal."""
|
Will raise an exception if the values are not equal."""
|
||||||
unittest.has_exception = True
|
|
||||||
self.assertEqual(first, second, msg=msg)
|
self.assertEqual(first, second, msg=msg)
|
||||||
unittest.has_exception = False
|
|
||||||
|
|
||||||
def assert_not_equal(self, first, second, msg=None):
|
def assert_not_equal(self, first, second, msg=None):
|
||||||
"""Asserts that the two values are not equal.
|
"""Asserts that the two values are not equal.
|
||||||
Will raise an exception if the values are equal."""
|
Will raise an exception if the values are equal."""
|
||||||
unittest.has_exception = True
|
|
||||||
self.assertNotEqual(first, second, msg=msg)
|
self.assertNotEqual(first, second, msg=msg)
|
||||||
unittest.has_exception = False
|
|
||||||
|
|
||||||
def assert_in(self, first, second, msg=None):
|
def assert_in(self, first, second, msg=None):
|
||||||
"""Asserts that the first string is in the second string.
|
"""Asserts that the first string is in the second string.
|
||||||
Will raise an exception if the first string is not in the second."""
|
Will raise an exception if the first string is not in the second."""
|
||||||
unittest.has_exception = True
|
|
||||||
self.assertIn(first, second, msg=msg)
|
self.assertIn(first, second, msg=msg)
|
||||||
unittest.has_exception = False
|
|
||||||
|
|
||||||
def assert_not_in(self, first, second, msg=None):
|
def assert_not_in(self, first, second, msg=None):
|
||||||
"""Asserts that the first string is not in the second string.
|
"""Asserts that the first string is not in the second string.
|
||||||
Will raise an exception if the first string is in the second string."""
|
Will raise an exception if the first string is in the second string."""
|
||||||
unittest.has_exception = True
|
|
||||||
self.assertNotIn(first, second, msg=msg)
|
self.assertNotIn(first, second, msg=msg)
|
||||||
unittest.has_exception = False
|
|
||||||
|
|
||||||
def assert_raises(self, *args, **kwargs):
|
def assert_raises(self, *args, **kwargs):
|
||||||
"""Asserts that the following block of code raises an exception.
|
"""Asserts that the following block of code raises an exception.
|
||||||
|
@ -6900,11 +6898,9 @@ class BaseCase(unittest.TestCase):
|
||||||
self.wait_for_ready_state_complete()
|
self.wait_for_ready_state_complete()
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
actual = self.get_page_title().strip()
|
actual = self.get_page_title().strip()
|
||||||
unittest.has_exception = True
|
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
expected, actual, error % (expected, actual)
|
expected, actual, error % (expected, actual)
|
||||||
)
|
)
|
||||||
unittest.has_exception = False
|
|
||||||
if self.demo_mode and not self.recorder_mode:
|
if self.demo_mode and not self.recorder_mode:
|
||||||
a_t = "ASSERT TITLE"
|
a_t = "ASSERT TITLE"
|
||||||
if self._language != "English":
|
if self._language != "English":
|
||||||
|
@ -6949,11 +6945,9 @@ class BaseCase(unittest.TestCase):
|
||||||
self.wait_for_ready_state_complete()
|
self.wait_for_ready_state_complete()
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
actual = self.get_page_title().strip()
|
actual = self.get_page_title().strip()
|
||||||
unittest.has_exception = True
|
|
||||||
self.assertIn(
|
self.assertIn(
|
||||||
expected, actual, error % (expected, actual)
|
expected, actual, error % (expected, actual)
|
||||||
)
|
)
|
||||||
unittest.has_exception = False
|
|
||||||
if self.demo_mode and not self.recorder_mode:
|
if self.demo_mode and not self.recorder_mode:
|
||||||
a_t = "ASSERT TITLE CONTAINS"
|
a_t = "ASSERT TITLE CONTAINS"
|
||||||
if self._language != "English":
|
if self._language != "English":
|
||||||
|
@ -6988,9 +6982,7 @@ class BaseCase(unittest.TestCase):
|
||||||
self.wait_for_ready_state_complete()
|
self.wait_for_ready_state_complete()
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
actual = self.get_current_url().strip()
|
actual = self.get_current_url().strip()
|
||||||
unittest.has_exception = True
|
|
||||||
self.assertEqual(expected, actual, error % (expected, actual))
|
self.assertEqual(expected, actual, error % (expected, actual))
|
||||||
unittest.has_exception = False
|
|
||||||
if self.demo_mode and not self.recorder_mode:
|
if self.demo_mode and not self.recorder_mode:
|
||||||
a_u = "ASSERT URL"
|
a_u = "ASSERT URL"
|
||||||
if self._language != "English":
|
if self._language != "English":
|
||||||
|
@ -7028,9 +7020,7 @@ class BaseCase(unittest.TestCase):
|
||||||
self.wait_for_ready_state_complete()
|
self.wait_for_ready_state_complete()
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
actual = self.get_current_url().strip()
|
actual = self.get_current_url().strip()
|
||||||
unittest.has_exception = True
|
|
||||||
self.assertIn(expected, actual, error % (expected, actual))
|
self.assertIn(expected, actual, error % (expected, actual))
|
||||||
unittest.has_exception = False
|
|
||||||
if self.demo_mode and not self.recorder_mode:
|
if self.demo_mode and not self.recorder_mode:
|
||||||
a_u = "ASSERT URL CONTAINS"
|
a_u = "ASSERT URL CONTAINS"
|
||||||
if self._language != "English":
|
if self._language != "English":
|
||||||
|
@ -7127,7 +7117,6 @@ class BaseCase(unittest.TestCase):
|
||||||
er_str = str(errors)
|
er_str = str(errors)
|
||||||
er_str = er_str.replace("[{", "[\n{").replace("}, {", "},\n{")
|
er_str = er_str.replace("[{", "[\n{").replace("}, {", "},\n{")
|
||||||
current_url = self.get_current_url()
|
current_url = self.get_current_url()
|
||||||
unittest.has_exception = True
|
|
||||||
raise Exception(
|
raise Exception(
|
||||||
"JavaScript errors found on %s => %s" % (current_url, er_str)
|
"JavaScript errors found on %s => %s" % (current_url, er_str)
|
||||||
)
|
)
|
||||||
|
@ -7683,9 +7672,7 @@ class BaseCase(unittest.TestCase):
|
||||||
|
|
||||||
def fail(self, msg=None):
|
def fail(self, msg=None):
|
||||||
"""Fail immediately, with the given message."""
|
"""Fail immediately, with the given message."""
|
||||||
unittest.has_exception = True
|
|
||||||
super().fail(msg)
|
super().fail(msg)
|
||||||
raise self.failureException(msg)
|
|
||||||
|
|
||||||
def skip(self, reason=""):
|
def skip(self, reason=""):
|
||||||
"""Mark the test as Skipped."""
|
"""Mark the test as Skipped."""
|
||||||
|
@ -9463,7 +9450,10 @@ class BaseCase(unittest.TestCase):
|
||||||
raise VisualException(minified_exception)
|
raise VisualException(minified_exception)
|
||||||
|
|
||||||
def _process_visual_baseline_logs(self):
|
def _process_visual_baseline_logs(self):
|
||||||
if not (python3_11_or_newer or "--pdb" in sys.argv):
|
if not (
|
||||||
|
(python3_11_or_newer and py311_patch2)
|
||||||
|
or "--pdb" in sys.argv
|
||||||
|
):
|
||||||
return
|
return
|
||||||
self.__process_visual_baseline_logs()
|
self.__process_visual_baseline_logs()
|
||||||
|
|
||||||
|
@ -9837,7 +9827,6 @@ class BaseCase(unittest.TestCase):
|
||||||
|
|
||||||
def __check_scope(self):
|
def __check_scope(self):
|
||||||
if hasattr(self, "browser"): # self.browser stores the type of browser
|
if hasattr(self, "browser"): # self.browser stores the type of browser
|
||||||
unittest.has_exception = False
|
|
||||||
return # All good: setUp() already initialized variables in "self"
|
return # All good: setUp() already initialized variables in "self"
|
||||||
else:
|
else:
|
||||||
message = (
|
message = (
|
||||||
|
@ -9853,7 +9842,6 @@ class BaseCase(unittest.TestCase):
|
||||||
"\n variables, which are initialized during the setUp() method"
|
"\n variables, which are initialized during the setUp() method"
|
||||||
"\n that runs automatically before all tests called by pytest."
|
"\n that runs automatically before all tests called by pytest."
|
||||||
)
|
)
|
||||||
unittest.has_exception = True
|
|
||||||
raise OutOfScopeException(message)
|
raise OutOfScopeException(message)
|
||||||
|
|
||||||
############
|
############
|
||||||
|
@ -10109,7 +10097,6 @@ class BaseCase(unittest.TestCase):
|
||||||
if print_only:
|
if print_only:
|
||||||
print(exception_output)
|
print(exception_output)
|
||||||
else:
|
else:
|
||||||
unittest.has_exception = True
|
|
||||||
raise Exception(exception_output.replace("\\n", "\n"))
|
raise Exception(exception_output.replace("\\n", "\n"))
|
||||||
|
|
||||||
############
|
############
|
||||||
|
@ -13408,11 +13395,9 @@ class BaseCase(unittest.TestCase):
|
||||||
"""This method runs before every test begins.
|
"""This method runs before every test begins.
|
||||||
Be careful if a subclass of BaseCase overrides setUp().
|
Be careful if a subclass of BaseCase overrides setUp().
|
||||||
If so, add the following line to the subclass setUp() method:
|
If so, add the following line to the subclass setUp() method:
|
||||||
super().setUp()
|
super().setUp() """
|
||||||
"""
|
|
||||||
if not hasattr(self, "_using_sb_fixture") and self.__called_setup:
|
if not hasattr(self, "_using_sb_fixture") and self.__called_setup:
|
||||||
# This test already called setUp()
|
return # This test already called setUp()
|
||||||
return
|
|
||||||
self.__called_setup = True
|
self.__called_setup = True
|
||||||
self.__called_teardown = False
|
self.__called_teardown = False
|
||||||
self.masterqa_mode = masterqa_mode
|
self.masterqa_mode = masterqa_mode
|
||||||
|
@ -13902,8 +13887,6 @@ class BaseCase(unittest.TestCase):
|
||||||
# Some actions such as hover-clicking are different on mobile.
|
# Some actions such as hover-clicking are different on mobile.
|
||||||
self.mobile_emulator = False
|
self.mobile_emulator = False
|
||||||
|
|
||||||
unittest.has_exception = False
|
|
||||||
|
|
||||||
# Configure the test time limit (if used).
|
# Configure the test time limit (if used).
|
||||||
self.set_time_limit(self.time_limit)
|
self.set_time_limit(self.time_limit)
|
||||||
|
|
||||||
|
@ -14080,7 +14063,10 @@ class BaseCase(unittest.TestCase):
|
||||||
self.testcase_manager.update_testcase_data(data_payload)
|
self.testcase_manager.update_testcase_data(data_payload)
|
||||||
|
|
||||||
def _add_pytest_html_extra(self):
|
def _add_pytest_html_extra(self):
|
||||||
if not (python3_11_or_newer or "--pdb" in sys.argv):
|
if not (
|
||||||
|
(python3_11_or_newer and py311_patch2)
|
||||||
|
or "--pdb" in sys.argv
|
||||||
|
):
|
||||||
return
|
return
|
||||||
self.__add_pytest_html_extra()
|
self.__add_pytest_html_extra()
|
||||||
|
|
||||||
|
@ -14188,8 +14174,6 @@ class BaseCase(unittest.TestCase):
|
||||||
has_exception = sys.exc_info()[1] is not None
|
has_exception = sys.exc_info()[1] is not None
|
||||||
if self.__will_be_skipped and hasattr(self, "_using_sb_fixture"):
|
if self.__will_be_skipped and hasattr(self, "_using_sb_fixture"):
|
||||||
has_exception = False
|
has_exception = False
|
||||||
if python3_11_or_newer and unittest.has_exception:
|
|
||||||
has_exception = True
|
|
||||||
return has_exception
|
return has_exception
|
||||||
|
|
||||||
def __get_test_id(self):
|
def __get_test_id(self):
|
||||||
|
@ -14731,7 +14715,7 @@ class BaseCase(unittest.TestCase):
|
||||||
if (
|
if (
|
||||||
self.__has_exception()
|
self.__has_exception()
|
||||||
or self.save_screenshot_after_test
|
or self.save_screenshot_after_test
|
||||||
or python3_11_or_newer
|
or (python3_11_or_newer and py311_patch2)
|
||||||
or "--pdb" in sys.argv
|
or "--pdb" in sys.argv
|
||||||
):
|
):
|
||||||
self.__set_last_page_screenshot()
|
self.__set_last_page_screenshot()
|
||||||
|
@ -14742,7 +14726,10 @@ class BaseCase(unittest.TestCase):
|
||||||
self.__add_pytest_html_extra()
|
self.__add_pytest_html_extra()
|
||||||
|
|
||||||
def _log_fail_data(self):
|
def _log_fail_data(self):
|
||||||
if not (python3_11_or_newer or "--pdb" in sys.argv):
|
if not (
|
||||||
|
(python3_11_or_newer and py311_patch2)
|
||||||
|
or "--pdb" in sys.argv
|
||||||
|
):
|
||||||
return
|
return
|
||||||
test_id = self.__get_test_id()
|
test_id = self.__get_test_id()
|
||||||
test_logpath = os.path.join(self.log_path, test_id)
|
test_logpath = os.path.join(self.log_path, test_id)
|
||||||
|
@ -14801,12 +14788,102 @@ class BaseCase(unittest.TestCase):
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def _addSkip(self, result, test_case, reason):
|
||||||
|
"""This method should NOT be called directly from tests.
|
||||||
|
(It will be called AUTOMATICALLY as needed.)"""
|
||||||
|
addSkip = getattr(result, 'addSkip', None)
|
||||||
|
if addSkip is not None:
|
||||||
|
addSkip(test_case, reason)
|
||||||
|
else:
|
||||||
|
import warnings
|
||||||
|
warnings.warn(
|
||||||
|
"TestResult has no addSkip method! Skips not reported!",
|
||||||
|
RuntimeWarning, 2
|
||||||
|
)
|
||||||
|
result.addSuccess(test_case)
|
||||||
|
|
||||||
|
def _callTestMethod(self, method):
|
||||||
|
"""This method should NOT be called directly from tests.
|
||||||
|
(It will be called AUTOMATICALLY as needed.)"""
|
||||||
|
method()
|
||||||
|
|
||||||
|
def run(self, result=None):
|
||||||
|
"""Overwrite the unittest run() method for Python 3.11 or newer.
|
||||||
|
This method should NOT be called directly from tests.
|
||||||
|
(It will be called AUTOMATICALLY as needed.)"""
|
||||||
|
if not python3_11_or_newer:
|
||||||
|
return super().run(result=result)
|
||||||
|
if result is None:
|
||||||
|
result = self.defaultTestResult()
|
||||||
|
startTestRun = getattr(result, 'startTestRun', None)
|
||||||
|
stopTestRun = getattr(result, 'stopTestRun', None)
|
||||||
|
if startTestRun is not None:
|
||||||
|
startTestRun()
|
||||||
|
else:
|
||||||
|
stopTestRun = None
|
||||||
|
result.startTest(self)
|
||||||
|
try:
|
||||||
|
testMethod = getattr(self, self._testMethodName)
|
||||||
|
if (
|
||||||
|
getattr(self.__class__, "__unittest_skip__", False)
|
||||||
|
or getattr(testMethod, "__unittest_skip__", False)
|
||||||
|
):
|
||||||
|
skip_why = (
|
||||||
|
getattr(self.__class__, '__unittest_skip_why__', '')
|
||||||
|
or getattr(testMethod, '__unittest_skip_why__', '')
|
||||||
|
)
|
||||||
|
self._addSkip(result, self, skip_why)
|
||||||
|
return result
|
||||||
|
expecting_failure = (
|
||||||
|
getattr(self, "__unittest_expecting_failure__", False)
|
||||||
|
or getattr(testMethod, "__unittest_expecting_failure__", False)
|
||||||
|
)
|
||||||
|
outcome = unittest_helper._Outcome(result)
|
||||||
|
try:
|
||||||
|
self._outcome = outcome
|
||||||
|
with outcome.testPartExecutor(self):
|
||||||
|
self._callSetUp()
|
||||||
|
if outcome.success:
|
||||||
|
outcome.expecting_failure = expecting_failure
|
||||||
|
with outcome.testPartExecutor(self, isTest=True):
|
||||||
|
self._callTestMethod(testMethod)
|
||||||
|
outcome.expecting_failure = False
|
||||||
|
with outcome.testPartExecutor(self):
|
||||||
|
self._callTearDown()
|
||||||
|
self.doCleanups()
|
||||||
|
for test, reason in outcome.skipped:
|
||||||
|
self._addSkip(result, test, reason)
|
||||||
|
for test, exc_info in outcome.errors:
|
||||||
|
if exc_info is not None:
|
||||||
|
if issubclass(exc_info[0], self.failureException):
|
||||||
|
result.addFailure(test, exc_info)
|
||||||
|
else:
|
||||||
|
result.addError(test, exc_info)
|
||||||
|
if outcome.success:
|
||||||
|
if expecting_failure:
|
||||||
|
if outcome.expectedFailure:
|
||||||
|
self._addExpectedFailure(
|
||||||
|
result, outcome.expectedFailure
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self._addUnexpectedSuccess(result)
|
||||||
|
else:
|
||||||
|
result.addSuccess(self)
|
||||||
|
return result
|
||||||
|
finally:
|
||||||
|
outcome.errors.clear()
|
||||||
|
outcome.expectedFailure = None
|
||||||
|
self._outcome = None
|
||||||
|
finally:
|
||||||
|
result.stopTest(self)
|
||||||
|
if stopTestRun is not None:
|
||||||
|
stopTestRun()
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
"""This method runs after every test completes.
|
"""This method runs after every test completes.
|
||||||
Be careful if a subclass of BaseCase overrides setUp().
|
Be careful if a subclass of BaseCase overrides setUp().
|
||||||
If so, add the following line to the subclass's tearDown() method:
|
If so, add the following line to the subclass's tearDown() method:
|
||||||
super().tearDown()
|
super().tearDown() """
|
||||||
"""
|
|
||||||
if not hasattr(self, "_using_sb_fixture") and self.__called_teardown:
|
if not hasattr(self, "_using_sb_fixture") and self.__called_teardown:
|
||||||
# This test already called tearDown()
|
# This test already called tearDown()
|
||||||
return
|
return
|
||||||
|
@ -14900,7 +14977,10 @@ class BaseCase(unittest.TestCase):
|
||||||
self.__add_pytest_html_extra()
|
self.__add_pytest_html_extra()
|
||||||
sb_config._has_logs = True
|
sb_config._has_logs = True
|
||||||
elif (
|
elif (
|
||||||
(python3_11_or_newer or "--pdb" in sys.argv)
|
(
|
||||||
|
(python3_11_or_newer and py311_patch2)
|
||||||
|
or "--pdb" in sys.argv
|
||||||
|
)
|
||||||
and not has_exception
|
and not has_exception
|
||||||
):
|
):
|
||||||
# Handle a bug where exceptions aren't seen
|
# Handle a bug where exceptions aren't seen
|
||||||
|
|
|
@ -41,6 +41,13 @@ class ValidEnvs:
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class PatchPy311:
|
||||||
|
# Now that unittest is "patched/fixed" in Python 3.11 and up,
|
||||||
|
# this second patch might not be needed to fix error-handling.
|
||||||
|
# Enabling this might slow things slightly to fix some things.
|
||||||
|
PATCH = False
|
||||||
|
|
||||||
|
|
||||||
class PageLoadStrategy:
|
class PageLoadStrategy:
|
||||||
# Usage Example => "--pls=none"
|
# Usage Example => "--pls=none"
|
||||||
NORMAL = "normal"
|
NORMAL = "normal"
|
||||||
|
|
|
@ -23,7 +23,6 @@ By.PARTIAL_LINK_TEXT # "partial link text"
|
||||||
import codecs
|
import codecs
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
import unittest
|
|
||||||
from selenium.common.exceptions import ElementNotInteractableException
|
from selenium.common.exceptions import ElementNotInteractableException
|
||||||
from selenium.common.exceptions import ElementNotVisibleException
|
from selenium.common.exceptions import ElementNotVisibleException
|
||||||
from selenium.common.exceptions import NoAlertPresentException
|
from selenium.common.exceptions import NoAlertPresentException
|
||||||
|
@ -225,7 +224,6 @@ def hover_element(driver, element):
|
||||||
|
|
||||||
|
|
||||||
def timeout_exception(exception, message):
|
def timeout_exception(exception, message):
|
||||||
unittest.has_exception = True
|
|
||||||
exc, msg = shared_utils.format_exc(exception, message)
|
exc, msg = shared_utils.format_exc(exception, message)
|
||||||
raise exc(msg)
|
raise exc(msg)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
import sys
|
||||||
|
from contextlib import contextmanager
|
||||||
|
from unittest.case import _ShouldStop, SkipTest
|
||||||
|
|
||||||
|
|
||||||
|
class _Outcome(object):
|
||||||
|
def __init__(self, result=None):
|
||||||
|
self.expecting_failure = False
|
||||||
|
self.result = result
|
||||||
|
self.result_supports_subtests = hasattr(result, "addSubTest")
|
||||||
|
self.success = True
|
||||||
|
self.skipped = []
|
||||||
|
self.expectedFailure = None
|
||||||
|
self.errors = []
|
||||||
|
|
||||||
|
@contextmanager
|
||||||
|
def testPartExecutor(self, test_case, isTest=False):
|
||||||
|
old_success = self.success
|
||||||
|
self.success = True
|
||||||
|
try:
|
||||||
|
yield
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
raise
|
||||||
|
except SkipTest as e:
|
||||||
|
self.success = False
|
||||||
|
self.skipped.append((test_case, str(e)))
|
||||||
|
except _ShouldStop:
|
||||||
|
pass
|
||||||
|
except Exception:
|
||||||
|
exc_info = sys.exc_info()
|
||||||
|
if self.expecting_failure:
|
||||||
|
self.expectedFailure = exc_info
|
||||||
|
else:
|
||||||
|
self.success = False
|
||||||
|
self.errors.append((test_case, exc_info))
|
||||||
|
exc_info = None
|
||||||
|
else:
|
||||||
|
if self.result_supports_subtests and self.success:
|
||||||
|
self.errors.append((test_case, None))
|
||||||
|
finally:
|
||||||
|
self.success = self.success and old_success
|
|
@ -13,6 +13,7 @@ from seleniumbase.fixtures import constants
|
||||||
python3_11_or_newer = False
|
python3_11_or_newer = False
|
||||||
if sys.version_info >= (3, 11):
|
if sys.version_info >= (3, 11):
|
||||||
python3_11_or_newer = True
|
python3_11_or_newer = True
|
||||||
|
py311_patch2 = constants.PatchPy311.PATCH = True
|
||||||
|
|
||||||
|
|
||||||
class Base(Plugin):
|
class Base(Plugin):
|
||||||
|
@ -276,7 +277,7 @@ class Base(Plugin):
|
||||||
test, self.test_count, self.duration
|
test, self.test_count, self.duration
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
if python3_11_or_newer:
|
if python3_11_or_newer and py311_patch2:
|
||||||
# Handle a bug on Python 3.11 where exceptions aren't seen
|
# Handle a bug on Python 3.11 where exceptions aren't seen
|
||||||
sb_config._browser_version = None
|
sb_config._browser_version = None
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -15,6 +15,7 @@ if sys.platform in ["win32", "win64", "x64"]:
|
||||||
python3_11_or_newer = False
|
python3_11_or_newer = False
|
||||||
if sys.version_info >= (3, 11):
|
if sys.version_info >= (3, 11):
|
||||||
python3_11_or_newer = True
|
python3_11_or_newer = True
|
||||||
|
py311_patch2 = constants.PatchPy311.PATCH
|
||||||
sys_argv = sys.argv
|
sys_argv = sys.argv
|
||||||
pytest_plugins = ["pytester"] # Adds the "testdir" fixture
|
pytest_plugins = ["pytester"] # Adds the "testdir" fixture
|
||||||
|
|
||||||
|
@ -1876,7 +1877,7 @@ def pytest_runtest_teardown(item):
|
||||||
if (
|
if (
|
||||||
(
|
(
|
||||||
sb_config._has_exception
|
sb_config._has_exception
|
||||||
or python3_11_or_newer
|
or (python3_11_or_newer and py311_patch2)
|
||||||
or "--pdb" in sys_argv
|
or "--pdb" in sys_argv
|
||||||
)
|
)
|
||||||
and sb_config.list_fp
|
and sb_config.list_fp
|
||||||
|
@ -2209,7 +2210,7 @@ def pytest_runtest_makereport(item, call):
|
||||||
sb_config._extra_dash_entries.append(test_id)
|
sb_config._extra_dash_entries.append(test_id)
|
||||||
elif (
|
elif (
|
||||||
sb_config._sbase_detected
|
sb_config._sbase_detected
|
||||||
and (python3_11_or_newer or "--pdb" in sys_argv)
|
and ((python3_11_or_newer and py311_patch2) or "--pdb" in sys_argv)
|
||||||
and (report.outcome == "failed" or "AssertionError" in str(call))
|
and (report.outcome == "failed" or "AssertionError" in str(call))
|
||||||
and not sb_config._has_exception
|
and not sb_config._has_exception
|
||||||
):
|
):
|
||||||
|
|
Loading…
Reference in New Issue