@@ -11388,6 +11388,11 @@ def __assert_eq(self, *args, **kwargs):
11388
11388
11389
11389
raise VisualException(minified_exception)
11390
11390
11391
+ def _process_visual_baseline_logs(self):
11392
+ if sys.version_info < (3, 11):
11393
+ return
11394
+ self.__process_visual_baseline_logs()
11395
+
11391
11396
def __process_visual_baseline_logs(self):
11392
11397
"""Save copies of baseline PNGs in "./latest_logs" during failures.
11393
11398
Also create a side_by_side.html file for visual comparisons."""
@@ -13033,6 +13038,31 @@ def setUp(self, masterqa_mode=False):
13033
13038
self.data_path = os.path.join(self.log_path, self.__get_test_id())
13034
13039
self.data_abspath = os.path.abspath(self.data_path)
13035
13040
13041
+ # Add _test_logpath value to sb_config
13042
+ test_id = self.__get_test_id()
13043
+ test_logpath = os.path.join(self.log_path, test_id)
13044
+ sb_config._test_logpath = test_logpath
13045
+
13046
+ # Add _process_dashboard_entry method to sb_config
13047
+ sb_config._process_dashboard_entry = self._process_dashboard_entry
13048
+
13049
+ # Add _add_pytest_html_extra method to sb_config
13050
+ sb_config._add_pytest_html_extra = self._add_pytest_html_extra
13051
+
13052
+ # Add _process_visual_baseline_logs method to sb_config
13053
+ sb_config._process_v_baseline_logs = self._process_visual_baseline_logs
13054
+
13055
+ # Add _log_fail_data method to sb_config
13056
+ sb_config._log_fail_data = self._log_fail_data
13057
+
13058
+ # Reset the last_page_screenshot variables
13059
+ sb_config._last_page_screenshot = None
13060
+ sb_config._last_page_screenshot_png = None
13061
+
13062
+ # Indictate to pytest reports that SeleniumBase is being used
13063
+ sb_config._sbase_detected = True
13064
+ sb_config._only_unittest = False
13065
+
13036
13066
# Mobile Emulator device metrics: CSS Width, CSS Height, & Pixel-Ratio
13037
13067
if self.device_metrics:
13038
13068
metrics_string = self.device_metrics
@@ -13075,15 +13105,11 @@ def setUp(self, masterqa_mode=False):
13075
13105
if self.dashboard:
13076
13106
if self._multithreaded:
13077
13107
with self.dash_lock:
13078
- sb_config._sbase_detected = True
13079
- sb_config._only_unittest = False
13080
13108
if not self._dash_initialized:
13081
13109
sb_config._dashboard_initialized = True
13082
13110
self._dash_initialized = True
13083
13111
self.__process_dashboard(False, init=True)
13084
13112
else:
13085
- sb_config._sbase_detected = True
13086
- sb_config._only_unittest = False
13087
13113
if not self._dash_initialized:
13088
13114
sb_config._dashboard_initialized = True
13089
13115
self._dash_initialized = True
@@ -13314,6 +13340,7 @@ def __set_last_page_source(self):
13314
13340
self.__last_page_source = (
13315
13341
constants.Warnings.PAGE_SOURCE_UNDEFINED
13316
13342
)
13343
+ sb_config._last_page_source = self.__last_page_source
13317
13344
13318
13345
def __get_exception_info(self):
13319
13346
exc_message = None
@@ -13368,6 +13395,11 @@ def __insert_test_result(self, state, err):
13368
13395
data_payload.message = "Skipped: (no reason given)"
13369
13396
self.testcase_manager.update_testcase_data(data_payload)
13370
13397
13398
+ def _add_pytest_html_extra(self):
13399
+ if sys.version_info < (3, 11):
13400
+ return
13401
+ self.__add_pytest_html_extra()
13402
+
13371
13403
def __add_pytest_html_extra(self):
13372
13404
if not self.__added_pytest_html_extra:
13373
13405
try:
@@ -13381,7 +13413,7 @@ def __add_pytest_html_extra(self):
13381
13413
extra_url["name"] = "URL"
13382
13414
extra_url["format"] = "url"
13383
13415
extra_url["format_type"] = "url"
13384
- extra_url["content"] = self.get_current_url()
13416
+ extra_url["content"] = self.__last_page_url
13385
13417
extra_url["mime_type"] = None
13386
13418
extra_url["extension"] = None
13387
13419
extra_image = {}
@@ -13465,8 +13497,12 @@ def __has_exception(self):
13465
13497
return True
13466
13498
else:
13467
13499
return False
13468
- elif python3 and hasattr(self, "_outcome"):
13469
- if hasattr(self._outcome, "errors") and self._outcome.errors:
13500
+ elif (
13501
+ python3
13502
+ and hasattr(self, "_outcome")
13503
+ and hasattr(self._outcome, "errors")
13504
+ ):
13505
+ if self._outcome.errors:
13470
13506
has_exception = True
13471
13507
else:
13472
13508
if python3:
@@ -13592,6 +13628,18 @@ def __create_log_path_as_needed(self, test_logpath):
13592
13628
except Exception:
13593
13629
pass # Only reachable during multi-threaded runs
13594
13630
13631
+ def _process_dashboard_entry(self, has_exception, init=False):
13632
+ if self._multithreaded:
13633
+ import fasteners
13634
+
13635
+ self.dash_lock = fasteners.InterProcessLock(
13636
+ constants.Dashboard.LOCKFILE
13637
+ )
13638
+ with self.dash_lock:
13639
+ self.__process_dashboard(has_exception, init)
13640
+ else:
13641
+ self.__process_dashboard(has_exception, init)
13642
+
13595
13643
def __process_dashboard(self, has_exception, init=False):
13596
13644
"""SeleniumBase Dashboard Processing"""
13597
13645
if self._multithreaded:
@@ -13995,6 +14043,66 @@ def save_teardown_screenshot(self):
13995
14043
if self.is_pytest:
13996
14044
self.__add_pytest_html_extra()
13997
14045
14046
+ def _log_fail_data(self):
14047
+ if sys.version_info < (3, 11):
14048
+ return
14049
+ test_id = self.__get_test_id()
14050
+ test_logpath = os.path.join(self.log_path, test_id)
14051
+ log_helper.log_test_failure_data(
14052
+ self,
14053
+ test_logpath,
14054
+ self.driver,
14055
+ self.browser,
14056
+ self.__last_page_url,
14057
+ )
14058
+
14059
+ def _get_browser_version(self):
14060
+ driver_capabilities = None
14061
+ if hasattr(self, "driver") and hasattr(self.driver, "capabilities"):
14062
+ driver_capabilities = self.driver.capabilities
14063
+ elif hasattr(sb_config, "_browser_version"):
14064
+ return sb_config._browser_version
14065
+ else:
14066
+ return "(Unknown Version)"
14067
+ if "version" in driver_capabilities:
14068
+ browser_version = driver_capabilities["version"]
14069
+ else:
14070
+ browser_version = driver_capabilities["browserVersion"]
14071
+ return browser_version
14072
+
14073
+ def _get_driver_name_and_version(self):
14074
+ if not hasattr(self.driver, "capabilities"):
14075
+ if hasattr(sb_config, "_driver_name_version"):
14076
+ return sb_config._driver_name_version
14077
+ else:
14078
+ return None
14079
+ driver = self.driver
14080
+ if driver.capabilities["browserName"].lower() == "chrome":
14081
+ cap_dict = driver.capabilities["chrome"]
14082
+ return (
14083
+ "chromedriver", cap_dict["chromedriverVersion"].split(" ")[0]
14084
+ )
14085
+ elif driver.capabilities["browserName"].lower() == "msedge":
14086
+ cap_dict = driver.capabilities["msedge"]
14087
+ return (
14088
+ "msedgedriver", cap_dict["msedgedriverVersion"].split(" ")[0]
14089
+ )
14090
+ elif driver.capabilities["browserName"].lower() == "opera":
14091
+ cap_dict = driver.capabilities["opera"]
14092
+ return (
14093
+ "operadriver", cap_dict["operadriverVersion"].split(" ")[0]
14094
+ )
14095
+ elif driver.capabilities["browserName"].lower() == "firefox":
14096
+ return (
14097
+ "geckodriver", driver.capabilities["moz:geckodriverVersion"]
14098
+ )
14099
+ elif self.browser == "safari":
14100
+ return ("safaridriver", self._get_browser_version())
14101
+ elif self.browser == "ie":
14102
+ return ("iedriver", self._get_browser_version())
14103
+ else:
14104
+ return None
14105
+
13998
14106
def tearDown(self):
13999
14107
"""
14000
14108
Be careful if a subclass of BaseCase overrides setUp()
@@ -14042,6 +14150,10 @@ def tearDown(self):
14042
14150
# *** Start tearDown() officially ***
14043
14151
self.__slow_mode_pause_if_active()
14044
14152
has_exception = self.__has_exception()
14153
+ sb_config._has_exception = has_exception
14154
+ sb_config._browser_version = self._get_browser_version()
14155
+ sb_config._driver_name_version = self._get_driver_name_and_version()
14156
+
14045
14157
if self.__overrided_default_timeouts:
14046
14158
# Reset default timeouts in case there are more tests
14047
14159
# These were changed in set_default_timeout()
@@ -14091,6 +14203,11 @@ def tearDown(self):
14091
14203
)
14092
14204
self.__add_pytest_html_extra()
14093
14205
sb_config._has_logs = True
14206
+ elif sys.version_info >= (3, 11) and not has_exception:
14207
+ # Handle a bug on Python 3.11 where exceptions aren't seen
14208
+ self.__set_last_page_screenshot()
14209
+ self.__set_last_page_url()
14210
+ self.__set_last_page_source()
14094
14211
if self.with_testing_base and has_exception:
14095
14212
test_logpath = os.path.join(self.log_path, test_id)
14096
14213
self.__create_log_path_as_needed(test_logpath)
@@ -14303,8 +14420,10 @@ def tearDown(self):
14303
14420
# (Nosetests / Behave / Pure Python) Close all open browser windows
14304
14421
self.__quit_all_drivers()
14305
14422
# Resume tearDown() for all test runners, (Pytest / Nosetests / Behave)
14306
- if has_exception and self.__visual_baseline_copies:
14307
- self.__process_visual_baseline_logs()
14423
+ if self.__visual_baseline_copies:
14424
+ sb_config._visual_baseline_copies = True
14425
+ if has_exception:
14426
+ self.__process_visual_baseline_logs()
14308
14427
if deferred_exception:
14309
14428
# User forgot to call "self.process_deferred_asserts()" in test
14310
14429
raise deferred_exception
0 commit comments