From c167a23a06793319a84997f2e7b251b6334116b0 Mon Sep 17 00:00:00 2001 From: Michael Mintz Date: Sat, 25 Jan 2025 17:35:50 -0500 Subject: [PATCH 1/4] Add shortcuts for using "Chrome for Testing" and "Chrome-Headless-Shell" --- help_docs/customizing_test_runs.md | 26 +++++++++++++++++++++++-- seleniumbase/plugins/driver_manager.py | 10 ++++++++++ seleniumbase/plugins/pytest_plugin.py | 18 +++++++++++++++++ seleniumbase/plugins/sb_manager.py | 10 ++++++++++ seleniumbase/plugins/selenium_plugin.py | 18 +++++++++++++++++ 5 files changed, 80 insertions(+), 2 deletions(-) diff --git a/help_docs/customizing_test_runs.md b/help_docs/customizing_test_runs.md index 615960ab905..722af066913 100644 --- a/help_docs/customizing_test_runs.md +++ b/help_docs/customizing_test_runs.md @@ -337,6 +337,8 @@ pytest --headless -n8 --dashboard --html=report.html -v --rs --crumbs The above not only runs tests in parallel processes, but it also tells tests in the same process to share the same browser session, runs the tests in headless mode, displays the full name of each test on a separate line, creates a real-time dashboard of the test results, and creates a full report after all tests complete. +-------- + 🎛️ For extra speed, run your tests using `chrome-headless-shell`: First, get `chrome-headless-shell` if you don't already have it: @@ -345,10 +347,10 @@ First, get `chrome-headless-shell` if you don't already have it: sbase get chs ``` -Then, run scripts with `binary_location` / `bl` set to `"chs"`: +Then, run scripts with `--chs` / `chs=True`: ```bash -pytest --bl="chs" -n8 --dashboard --html=report.html -v --rs +pytest --chs -n8 --dashboard --html=report.html -v --rs ``` That makes your tests run very quickly in headless mode. @@ -486,6 +488,26 @@ With the `SB()` and `Driver()` formats, the binary location is set via the `bina -------- +🎛️ To use the special `Chrome for Testing` binary: + +```bash +sbase get cft +``` + +Then, run scripts with `--cft` / `cft=True`: + +```bash +pytest --cft -n8 --dashboard --html=report.html -v --rs --headless +``` + +-------- + +(Note that `--chs` / `chs=True` activates `Chrome-Headless-Shell`) + +`Chrome-Headless-Shell` is the fastest version of Chrome, designed specifically for headless automation. (This mode is NOT compatible with UC Mode!) + +-------- +

Customizing default settings:

🎛️ An easy way to override [seleniumbase/config/settings.py](https://github.com/seleniumbase/SeleniumBase/blob/master/seleniumbase/config/settings.py) is by using a custom settings file. diff --git a/seleniumbase/plugins/driver_manager.py b/seleniumbase/plugins/driver_manager.py index 384e30d38c4..fcba10455dc 100644 --- a/seleniumbase/plugins/driver_manager.py +++ b/seleniumbase/plugins/driver_manager.py @@ -137,6 +137,8 @@ def Driver( guest=None, # Shortcut / Duplicate of "guest_mode". wire=None, # Shortcut / Duplicate of "use_wire". pls=None, # Shortcut / Duplicate of "page_load_strategy". + cft=None, # Use "Chrome for Testing" + chs=None, # Use "Chrome-Headless-Shell" ): """ * SeleniumBase Driver as a Python Context Manager or a returnable object. * @@ -550,6 +552,14 @@ def Driver( if arg.startswith("--bl="): binary_location = arg.split("--bl=")[1] break + if cft and not binary_location: + binary_location = "cft" + elif chs and not binary_location: + binary_location = "chs" + if "--cft" in sys_argv and not binary_location: + binary_location = "cft" + elif "--chs" in sys_argv and not binary_location: + binary_location = "chs" if ( binary_location and binary_location.lower() == "chs" diff --git a/seleniumbase/plugins/pytest_plugin.py b/seleniumbase/plugins/pytest_plugin.py index 4887d837248..9dceda430e9 100644 --- a/seleniumbase/plugins/pytest_plugin.py +++ b/seleniumbase/plugins/pytest_plugin.py @@ -184,6 +184,20 @@ def pytest_addoption(parser): default=False, help="""Shortcut for --browser=safari""", ) + parser.addoption( + "--cft", + action="store_true", + dest="use_cft", + default=False, + help="""Shortcut for using `Chrome for Testing`""", + ) + parser.addoption( + "--chs", + action="store_true", + dest="use_chs", + default=False, + help="""Shortcut for using `Chrome-Headless-Shell`""", + ) parser.addoption( "--with-selenium", action="store_true", @@ -1575,6 +1589,10 @@ def pytest_configure(config): sb_config.extension_dir = config.getoption("extension_dir") sb_config.disable_features = config.getoption("disable_features") sb_config.binary_location = config.getoption("binary_location") + if config.getoption("use_cft") and not sb_config.binary_location: + sb_config.binary_location = "cft" + elif config.getoption("use_chs") and not sb_config.binary_location: + sb_config.binary_location = "chs" if ( sb_config.binary_location and sb_config.binary_location.lower() == "chs" diff --git a/seleniumbase/plugins/sb_manager.py b/seleniumbase/plugins/sb_manager.py index 1f60832281a..e934d0feefb 100644 --- a/seleniumbase/plugins/sb_manager.py +++ b/seleniumbase/plugins/sb_manager.py @@ -119,6 +119,8 @@ def SB( pls=None, # Shortcut / Duplicate of "page_load_strategy". sjw=None, # Shortcut / Duplicate of "skip_js_waits". wfa=None, # Shortcut / Duplicate of "wait_for_angularjs". + cft=None, # Use "Chrome for Testing" + chs=None, # Use "Chrome-Headless-Shell" save_screenshot=None, # Save a screenshot at the end of each test. no_screenshot=None, # No screenshots saved unless tests directly ask it. page_load_strategy=None, # Set Chrome PLS to "normal", "eager", or "none". @@ -588,6 +590,14 @@ def SB( if arg.startswith("--bl="): binary_location = arg.split("--bl=")[1] break + if cft and not binary_location: + binary_location = "cft" + elif chs and not binary_location: + binary_location = "chs" + if "--cft" in sys_argv and not binary_location: + binary_location = "cft" + elif "--chs" in sys_argv and not binary_location: + binary_location = "chs" if ( binary_location and binary_location.lower() == "chs" diff --git a/seleniumbase/plugins/selenium_plugin.py b/seleniumbase/plugins/selenium_plugin.py index 2666e91c4a9..ba2fc7b59c2 100644 --- a/seleniumbase/plugins/selenium_plugin.py +++ b/seleniumbase/plugins/selenium_plugin.py @@ -144,6 +144,20 @@ def options(self, parser, env): default=False, help="""Shortcut for --browser=safari""", ) + parser.addoption( + "--cft", + action="store_true", + dest="use_cft", + default=False, + help="""Shortcut for using `Chrome for Testing`""", + ) + parser.addoption( + "--chs", + action="store_true", + dest="use_chs", + default=False, + help="""Shortcut for using `Chrome-Headless-Shell`""", + ) parser.addoption( "--cap_file", "--cap-file", @@ -1203,6 +1217,10 @@ def beforeTest(self, test): test.test.extension_dir = self.options.extension_dir test.test.disable_features = self.options.disable_features test.test.binary_location = self.options.binary_location + if self.options.use_cft and not test.test.binary_location: + test.test.binary_location = "cft" + elif self.options.use_chs and not test.test.binary_location: + test.test.binary_location = "chs" if ( test.test.binary_location and test.test.binary_location.lower() == "chs" From a6c0493a3ddccc798aa3a9549197514d2490d843 Mon Sep 17 00:00:00 2001 From: Michael Mintz Date: Sat, 25 Jan 2025 17:37:31 -0500 Subject: [PATCH 2/4] Error early when combining UC Mode with Chrome-Headless-Shell --- seleniumbase/core/browser_launcher.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/seleniumbase/core/browser_launcher.py b/seleniumbase/core/browser_launcher.py index 434275ef926..689b5b2fc99 100644 --- a/seleniumbase/core/browser_launcher.py +++ b/seleniumbase/core/browser_launcher.py @@ -2651,6 +2651,13 @@ def get_driver( if headless2 and browser_name == constants.Browser.FIREFOX: headless2 = False # Only for Chromium headless = True + if ( + is_using_uc(undetectable, browser_name) + and binary_location + and isinstance(binary_location, str) + and binary_location.lower() == "chs" + ): + raise Exception("UC Mode can't be used with Chrome-Headless-Shell!") if ( binary_location and isinstance(binary_location, str) From 02d13c66b44e66f83ab362c7d38b54af8d5ec9cc Mon Sep 17 00:00:00 2001 From: Michael Mintz Date: Sat, 25 Jan 2025 17:37:46 -0500 Subject: [PATCH 3/4] Refresh Python dependencies --- requirements.txt | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 9d0d4f974b6..91f767bdb80 100755 --- a/requirements.txt +++ b/requirements.txt @@ -3,7 +3,7 @@ packaging>=24.2 setuptools~=70.2;python_version<"3.10" setuptools>=75.8.0;python_version>="3.10" wheel>=0.45.1 -attrs>=24.3.0 +attrs>=25.1.0 certifi>=2024.12.14 exceptiongroup>=1.2.2 websockets~=13.1;python_version<"3.9" diff --git a/setup.py b/setup.py index b09da705aa5..4b692bafe63 100755 --- a/setup.py +++ b/setup.py @@ -152,7 +152,7 @@ 'setuptools~=70.2;python_version<"3.10"', # Newer ones had issues 'setuptools>=75.8.0;python_version>="3.10"', 'wheel>=0.45.1', - 'attrs>=24.3.0', + 'attrs>=25.1.0', "certifi>=2024.12.14", "exceptiongroup>=1.2.2", 'websockets~=13.1;python_version<"3.9"', From 6343194a4c6dd6112e932daa1b4eee122f551ea5 Mon Sep 17 00:00:00 2001 From: Michael Mintz Date: Sat, 25 Jan 2025 17:38:14 -0500 Subject: [PATCH 4/4] Version 4.34.3 --- seleniumbase/__version__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seleniumbase/__version__.py b/seleniumbase/__version__.py index 7772e500ce6..6c9b3c3956d 100755 --- a/seleniumbase/__version__.py +++ b/seleniumbase/__version__.py @@ -1,2 +1,2 @@ # seleniumbase package -__version__ = "4.34.2" +__version__ = "4.34.3"