Skip to content

Commit

Permalink
Merge pull request #3319 from seleniumbase/pytest-report-updates
Browse files Browse the repository at this point in the history
`pytest` report updates
  • Loading branch information
mdmintz authored Dec 6, 2024
2 parents f4c3f24 + e87ef69 commit a353c53
Show file tree
Hide file tree
Showing 8 changed files with 162 additions and 125 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ latest_report
report_archives
archived_reports
html_report.html
last_report.html
report.html
report.xml

Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ execnet==2.1.1
iniconfig==2.0.0
pluggy==1.5.0
pytest==8.3.4
pytest-html==4.1.1
pytest-html==4.0.2
pytest-metadata==3.1.1
pytest-ordering==0.6
pytest-rerunfailures==14.0;python_version<"3.9"
Expand Down
2 changes: 1 addition & 1 deletion seleniumbase/__version__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# seleniumbase package
__version__ = "4.33.4"
__version__ = "4.33.5"
1 change: 1 addition & 0 deletions seleniumbase/console_scripts/sb_mkdir.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ def main():
data.append("report_archives")
data.append("archived_reports")
data.append("html_report.html")
data.append("last_report.html")
data.append("report.html")
data.append("report.xml")
data.append("dashboard.html")
Expand Down
117 changes: 64 additions & 53 deletions seleniumbase/core/browser_launcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -817,6 +817,63 @@ def verify_pyautogui_has_a_headed_browser(driver):
)


def __install_pyautogui_if_missing():
try:
import pyautogui
with suppress(Exception):
use_pyautogui_ver = constants.PyAutoGUI.VER
if pyautogui.__version__ != use_pyautogui_ver:
del pyautogui
shared_utils.pip_install(
"pyautogui", version=use_pyautogui_ver
)
import pyautogui
except Exception:
print("\nPyAutoGUI required! Installing now...")
shared_utils.pip_install(
"pyautogui", version=constants.PyAutoGUI.VER
)
try:
import pyautogui
except Exception:
if (
IS_LINUX
and hasattr(sb_config, "xvfb")
and hasattr(sb_config, "headed")
and hasattr(sb_config, "headless")
and hasattr(sb_config, "headless2")
and (not sb_config.headed or sb_config.xvfb)
and not (sb_config.headless or sb_config.headless2)
):
from sbvirtualdisplay import Display
xvfb_width = 1366
xvfb_height = 768
if (
hasattr(sb_config, "_xvfb_width")
and sb_config._xvfb_width
and isinstance(sb_config._xvfb_width, int)
and hasattr(sb_config, "_xvfb_height")
and sb_config._xvfb_height
and isinstance(sb_config._xvfb_height, int)
):
xvfb_width = sb_config._xvfb_width
xvfb_height = sb_config._xvfb_height
if xvfb_width < 1024:
xvfb_width = 1024
sb_config._xvfb_width = xvfb_width
if xvfb_height < 768:
xvfb_height = 768
sb_config._xvfb_height = xvfb_height
with suppress(Exception):
xvfb_display = Display(
visible=True,
size=(xvfb_width, xvfb_height),
backend="xvfb",
use_xauth=True,
)
xvfb_display.start()


def install_pyautogui_if_missing(driver):
verify_pyautogui_has_a_headed_browser(driver)
pip_find_lock = fasteners.InterProcessLock(
Expand All @@ -829,61 +886,15 @@ def install_pyautogui_if_missing(driver):
# Need write permissions
with suppress(Exception):
make_writable(constants.PipInstall.FINDLOCK)
with pip_find_lock: # Prevent issues with multiple processes
try:
import pyautogui
with suppress(Exception):
use_pyautogui_ver = constants.PyAutoGUI.VER
if pyautogui.__version__ != use_pyautogui_ver:
del pyautogui
shared_utils.pip_install(
"pyautogui", version=use_pyautogui_ver
)
import pyautogui
with pip_find_lock:
pass
except Exception:
print("\nPyAutoGUI required! Installing now...")
shared_utils.pip_install(
"pyautogui", version=constants.PyAutoGUI.VER
)
try:
import pyautogui
except Exception:
if (
IS_LINUX
and hasattr(sb_config, "xvfb")
and hasattr(sb_config, "headed")
and hasattr(sb_config, "headless")
and hasattr(sb_config, "headless2")
and (not sb_config.headed or sb_config.xvfb)
and not (sb_config.headless or sb_config.headless2)
):
from sbvirtualdisplay import Display
xvfb_width = 1366
xvfb_height = 768
if (
hasattr(sb_config, "_xvfb_width")
and sb_config._xvfb_width
and isinstance(sb_config._xvfb_width, int)
and hasattr(sb_config, "_xvfb_height")
and sb_config._xvfb_height
and isinstance(sb_config._xvfb_height, int)
):
xvfb_width = sb_config._xvfb_width
xvfb_height = sb_config._xvfb_height
if xvfb_width < 1024:
xvfb_width = 1024
sb_config._xvfb_width = xvfb_width
if xvfb_height < 768:
xvfb_height = 768
sb_config._xvfb_height = xvfb_height
with suppress(Exception):
xvfb_display = Display(
visible=True,
size=(xvfb_width, xvfb_height),
backend="xvfb",
use_xauth=True,
)
xvfb_display.start()
# Since missing permissions, skip the locks
__install_pyautogui_if_missing()
return
with pip_find_lock: # Prevent issues with multiple processes
__install_pyautogui_if_missing()


def get_configured_pyautogui(pyautogui_copy):
Expand Down
148 changes: 79 additions & 69 deletions seleniumbase/fixtures/base_case.py
Original file line number Diff line number Diff line change
Expand Up @@ -13974,12 +13974,82 @@ def __activate_standard_virtual_display(self):
self.headless_active = True
sb_config.headless_active = True

def __activate_virtual_display(self):
if self.undetectable and not (self.headless or self.headless2):
from sbvirtualdisplay import Display
import Xlib.display
try:
if not self._xvfb_width:
self._xvfb_width = 1366
if not self._xvfb_height:
self._xvfb_height = 768
self._xvfb_display = Display(
visible=True,
size=(self._xvfb_width, self._xvfb_height),
backend="xvfb",
use_xauth=True,
)
self._xvfb_display.start()
if "DISPLAY" not in os.environ.keys():
print(
"\nX11 display failed! Will use regular xvfb!"
)
self.__activate_standard_virtual_display()
except Exception as e:
if hasattr(e, "msg"):
print("\n" + str(e.msg))
else:
print(e)
print("\nX11 display failed! Will use regular xvfb!")
self.__activate_standard_virtual_display()
return
pyautogui_is_installed = False
try:
import pyautogui
with suppress(Exception):
use_pyautogui_ver = constants.PyAutoGUI.VER
if pyautogui.__version__ != use_pyautogui_ver:
del pyautogui # To get newer ver
shared_utils.pip_install(
"pyautogui", version=use_pyautogui_ver
)
import pyautogui
pyautogui_is_installed = True
except Exception:
message = (
"PyAutoGUI is required for UC Mode on Linux! "
"Installing now..."
)
print("\n" + message)
shared_utils.pip_install(
"pyautogui", version=constants.PyAutoGUI.VER
)
import pyautogui
pyautogui_is_installed = True
if (
pyautogui_is_installed
and hasattr(pyautogui, "_pyautogui_x11")
):
try:
pyautogui._pyautogui_x11._display = (
Xlib.display.Display(os.environ['DISPLAY'])
)
sb_config._pyautogui_x11_display = (
pyautogui._pyautogui_x11._display
)
except Exception as e:
if hasattr(e, "msg"):
print("\n" + str(e.msg))
else:
print(e)
else:
self.__activate_standard_virtual_display()

def __activate_virtual_display_as_needed(self):
"""This is only needed on Linux.
The "--xvfb" arg is still useful, as it prevents headless mode,
which is the default mode on Linux unless using another arg."""
if "linux" in sys.platform and (not self.headed or self.xvfb):
from sbvirtualdisplay import Display
pip_find_lock = fasteners.InterProcessLock(
constants.PipInstall.FINDLOCK
)
Expand All @@ -13992,75 +14062,15 @@ def __activate_virtual_display_as_needed(self):
mode = os.stat(constants.PipInstall.FINDLOCK).st_mode
mode |= (mode & 0o444) >> 1 # copy R bits to W
os.chmod(constants.PipInstall.FINDLOCK, mode)
try:
with pip_find_lock:
pass
except Exception:
# Since missing permissions, skip the locks
self.__activate_virtual_display()
return
with pip_find_lock: # Prevent issues with multiple processes
if self.undetectable and not (self.headless or self.headless2):
import Xlib.display
try:
if not self._xvfb_width:
self._xvfb_width = 1366
if not self._xvfb_height:
self._xvfb_height = 768
self._xvfb_display = Display(
visible=True,
size=(self._xvfb_width, self._xvfb_height),
backend="xvfb",
use_xauth=True,
)
self._xvfb_display.start()
if "DISPLAY" not in os.environ.keys():
print(
"\nX11 display failed! Will use regular xvfb!"
)
self.__activate_standard_virtual_display()
except Exception as e:
if hasattr(e, "msg"):
print("\n" + str(e.msg))
else:
print(e)
print("\nX11 display failed! Will use regular xvfb!")
self.__activate_standard_virtual_display()
return
pyautogui_is_installed = False
try:
import pyautogui
with suppress(Exception):
use_pyautogui_ver = constants.PyAutoGUI.VER
if pyautogui.__version__ != use_pyautogui_ver:
del pyautogui # To get newer ver
shared_utils.pip_install(
"pyautogui", version=use_pyautogui_ver
)
import pyautogui
pyautogui_is_installed = True
except Exception:
message = (
"PyAutoGUI is required for UC Mode on Linux! "
"Installing now..."
)
print("\n" + message)
shared_utils.pip_install(
"pyautogui", version=constants.PyAutoGUI.VER
)
import pyautogui
pyautogui_is_installed = True
if (
pyautogui_is_installed
and hasattr(pyautogui, "_pyautogui_x11")
):
try:
pyautogui._pyautogui_x11._display = (
Xlib.display.Display(os.environ['DISPLAY'])
)
sb_config._pyautogui_x11_display = (
pyautogui._pyautogui_x11._display
)
except Exception as e:
if hasattr(e, "msg"):
print("\n" + str(e.msg))
else:
print(e)
else:
self.__activate_standard_virtual_display()
self.__activate_virtual_display()

def __ad_block_as_needed(self):
"""This is an internal method for handling ad-blocking.
Expand Down
14 changes: 14 additions & 0 deletions seleniumbase/plugins/pytest_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -1709,6 +1709,7 @@ def pytest_configure(config):
sb_config._saved_dashboard_pie = None # Copy of pie chart for html report
sb_config._dash_final_summary = None # Dash status to add to html report
sb_config._html_report_name = None # The name of the pytest html report
sb_config._html_report_copy = None # The copy of the pytest html report

arg_join = " ".join(sys_argv)
if (
Expand Down Expand Up @@ -1742,6 +1743,7 @@ def pytest_configure(config):
if sb_config.dashboard:
if sb_config._html_report_name == "dashboard.html":
sb_config._dash_is_html_report = True
sb_config._html_report_copy = "last_report.html"

# Recorder Mode does not support multi-threaded / multi-process runs.
if sb_config.recorder_mode and sb_config._multithreaded:
Expand Down Expand Up @@ -2151,6 +2153,10 @@ def _perform_pytest_unconfigure_(config):
html_report_path = os.path.join(
abs_path, sb_config._html_report_name
)
if sb_config._html_report_copy:
html_report_path_copy = os.path.join(
abs_path, sb_config._html_report_copy
)
if (
sb_config._using_html_report
and html_report_path
Expand Down Expand Up @@ -2201,6 +2207,8 @@ def _perform_pytest_unconfigure_(config):
)
with open(html_report_path, "w", encoding="utf-8") as f:
f.write(the_html_r) # Finalize the HTML report
with open(html_report_path_copy, "w", encoding="utf-8") as f:
f.write(the_html_r) # Finalize the HTML report
# Done with "pytest_unconfigure" unless using the Dashboard
return
stamp = ""
Expand Down Expand Up @@ -2288,6 +2296,10 @@ def _perform_pytest_unconfigure_(config):
html_report_path = os.path.join(
abs_path, sb_config._html_report_name
)
if sb_config._html_report_copy:
html_report_path_copy = os.path.join(
abs_path, sb_config._html_report_copy
)
if (
sb_config._using_html_report
and html_report_path
Expand Down Expand Up @@ -2358,6 +2370,8 @@ def _perform_pytest_unconfigure_(config):
)
with open(html_report_path, "w", encoding="utf-8") as f:
f.write(the_html_r) # Finalize the HTML report
with open(html_report_path_copy, "w", encoding="utf-8") as f:
f.write(the_html_r) # Finalize the HTML report
except KeyboardInterrupt:
pass
except Exception:
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@
'iniconfig==2.0.0',
'pluggy==1.5.0',
'pytest==8.3.4',
"pytest-html==4.1.1",
"pytest-html==4.0.2",
'pytest-metadata==3.1.1',
"pytest-ordering==0.6",
'pytest-rerunfailures==14.0;python_version<"3.9"',
Expand Down

0 comments on commit a353c53

Please sign in to comment.