Skip to content

Commit 5dc8143

Browse files
committed
Add special options for setting the binary location
1 parent a44a1d5 commit 5dc8143

File tree

7 files changed

+250
-3
lines changed

7 files changed

+250
-3
lines changed

help_docs/customizing_test_runs.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,27 @@ Note that different options could lead to the same result. (Eg. If you have the
449449

450450
--------
451451

452+
<h3><img src="https://seleniumbase.github.io/img/green_logo.png" title="SeleniumBase" width="32" /> Setting the binary location:</h3>
453+
454+
🔵 By default, SeleniumBase uses the browser binary detected on the System PATH.
455+
456+
🎛️ To change this default behavior, you can use:
457+
458+
```bash
459+
pytest --binary-location=PATH
460+
```
461+
462+
The `PATH` in `--binary-location=PATH` / `--bl=PATH` can be:
463+
* A relative or exact path to the browser binary.
464+
* `"cft"` as a special option for `Chrome for Testing`.
465+
* `"chs"` as a special option for `Chrome-Headless-Shell`.
466+
467+
Before using the `"cft"` / `"chs"` options, call `sbase get cft` / `sbase get chs` in order to download the specified binaries into the `seleniumbase/drivers` folder. The default version is the latest stable version on https://googlechromelabs.github.io/chrome-for-testing/. You can change that by specifying the arg as a parameter. (Eg. `sbase get cft 131`, `sbase get chs 132`, etc.)
468+
469+
With the `SB()` and `Driver()` formats, the binary location is set via the `binary_location` parameter.
470+
471+
--------
472+
452473
<h3><img src="https://seleniumbase.github.io/img/green_logo.png" title="SeleniumBase" width="32" /> Customizing default settings:</h3>
453474

454475
🎛️ 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.

seleniumbase/behave/behave_sb.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -482,8 +482,8 @@ def get_configured_sb(context):
482482
extension_dir = sb.extension_dir # revert to default
483483
sb.extension_dir = extension_dir
484484
continue
485-
# Handle: -D binary-location=PATH / binary_location=PATH
486-
if low_key in ["binary-location", "binary_location"]:
485+
# Handle: -D binary-location=PATH / binary_location=PATH / bl=PATH
486+
if low_key in ["binary-location", "binary_location", "bl"]:
487487
binary_location = userdata[key]
488488
if binary_location == "true":
489489
binary_location = sb.binary_location # revert to default
@@ -884,6 +884,14 @@ def get_configured_sb(context):
884884
sb.headless = True # Firefox has regular headless
885885
elif sb.browser not in ["chrome", "edge"]:
886886
sb.headless2 = False # Only for Chromium browsers
887+
if (
888+
sb.binary_location
889+
and sb.binary_location.lower() == "chs"
890+
and sb.browser == "chrome"
891+
):
892+
sb.headless = True
893+
sb.headless1 = False
894+
sb.headless2 = False
887895
# Recorder Mode only supports Chromium browsers.
888896
if sb.recorder_ext and (sb.browser not in ["chrome", "edge"]):
889897
raise Exception(

seleniumbase/core/browser_launcher.py

Lines changed: 145 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import fasteners
22
import logging
33
import os
4+
import platform
45
import re
56
import shutil
67
import subprocess
@@ -64,6 +65,7 @@
6465
LOCAL_IEDRIVER = None
6566
LOCAL_HEADLESS_IEDRIVER = None
6667
LOCAL_UC_DRIVER = None
68+
ARCH = platform.architecture()[0]
6769
IS_ARM_MAC = shared_utils.is_arm_mac()
6870
IS_MAC = shared_utils.is_mac()
6971
IS_LINUX = shared_utils.is_linux()
@@ -2657,6 +2659,118 @@ def get_driver(
26572659
or browser_name == constants.Browser.EDGE
26582660
)
26592661
):
2662+
if (
2663+
binary_location.lower() == "cft"
2664+
and browser_name == constants.Browser.GOOGLE_CHROME
2665+
):
2666+
binary_folder = None
2667+
if IS_MAC:
2668+
if IS_ARM_MAC:
2669+
binary_folder = "chrome-mac-arm64"
2670+
else:
2671+
binary_folder = "chrome-mac-x64"
2672+
elif IS_LINUX:
2673+
binary_folder = "chrome-linux64"
2674+
elif IS_WINDOWS:
2675+
if "64" in ARCH:
2676+
binary_folder = "chrome-win64"
2677+
else:
2678+
binary_folder = "chrome-win32"
2679+
if binary_folder:
2680+
binary_location = os.path.join(DRIVER_DIR, binary_folder)
2681+
if not os.path.exists(binary_location):
2682+
from seleniumbase.console_scripts import sb_install
2683+
args = " ".join(sys.argv)
2684+
if not (
2685+
"-n" in sys.argv or " -n=" in args or args == "-c"
2686+
):
2687+
# (Not multithreaded)
2688+
sys_args = sys.argv # Save a copy of current sys args
2689+
log_d(
2690+
"\nWarning: Chrome for Testing binary not found..."
2691+
)
2692+
try:
2693+
sb_install.main(override="cft")
2694+
except Exception as e:
2695+
log_d("\nWarning: Chrome download failed: %s" % e)
2696+
sys.argv = sys_args # Put back the original sys args
2697+
else:
2698+
chrome_fixing_lock = fasteners.InterProcessLock(
2699+
constants.MultiBrowser.DRIVER_FIXING_LOCK
2700+
)
2701+
with chrome_fixing_lock:
2702+
with suppress(Exception):
2703+
shared_utils.make_writable(
2704+
constants.MultiBrowser.DRIVER_FIXING_LOCK
2705+
)
2706+
if not os.path.exists(binary_location):
2707+
sys_args = sys.argv # Save a copy of sys args
2708+
log_d(
2709+
"\nWarning: "
2710+
"Chrome for Testing binary not found..."
2711+
)
2712+
sb_install.main(override="cft")
2713+
sys.argv = sys_args # Put back original args
2714+
else:
2715+
binary_location = None
2716+
if (
2717+
binary_location.lower() == "chs"
2718+
and browser_name == constants.Browser.GOOGLE_CHROME
2719+
):
2720+
binary_folder = None
2721+
if IS_MAC:
2722+
if IS_ARM_MAC:
2723+
binary_folder = "chrome-headless-shell-mac-arm64"
2724+
else:
2725+
binary_folder = "chrome-headless-shell-mac-x64"
2726+
elif IS_LINUX:
2727+
binary_folder = "chrome-headless-shell-linux64"
2728+
elif IS_WINDOWS:
2729+
if "64" in ARCH:
2730+
binary_folder = "chrome-headless-shell-win64"
2731+
else:
2732+
binary_folder = "chrome-headless-shell-win32"
2733+
if binary_folder:
2734+
binary_location = os.path.join(DRIVER_DIR, binary_folder)
2735+
if not os.path.exists(binary_location):
2736+
from seleniumbase.console_scripts import sb_install
2737+
args = " ".join(sys.argv)
2738+
if not (
2739+
"-n" in sys.argv or " -n=" in args or args == "-c"
2740+
):
2741+
# (Not multithreaded)
2742+
sys_args = sys.argv # Save a copy of current sys args
2743+
log_d(
2744+
"\nWarning: "
2745+
"Chrome-Headless-Shell binary not found..."
2746+
)
2747+
try:
2748+
sb_install.main(override="chs")
2749+
except Exception as e:
2750+
log_d(
2751+
"\nWarning: "
2752+
"Chrome-Headless-Shell download failed: %s" % e
2753+
)
2754+
sys.argv = sys_args # Put back the original sys args
2755+
else:
2756+
chrome_fixing_lock = fasteners.InterProcessLock(
2757+
constants.MultiBrowser.DRIVER_FIXING_LOCK
2758+
)
2759+
with chrome_fixing_lock:
2760+
with suppress(Exception):
2761+
shared_utils.make_writable(
2762+
constants.MultiBrowser.DRIVER_FIXING_LOCK
2763+
)
2764+
if not os.path.exists(binary_location):
2765+
sys_args = sys.argv # Save a copy of sys args
2766+
log_d(
2767+
"\nWarning: "
2768+
"Chrome-Headless-Shell binary not found..."
2769+
)
2770+
sb_install.main(override="chs")
2771+
sys.argv = sys_args # Put back original args
2772+
else:
2773+
binary_location = None
26602774
if not os.path.exists(binary_location):
26612775
log_d(
26622776
"\nWarning: The Chromium binary specified (%s) was NOT found!"
@@ -2666,7 +2780,7 @@ def get_driver(
26662780
elif binary_location.endswith("/") or binary_location.endswith("\\"):
26672781
log_d(
26682782
"\nWarning: The Chromium binary path must be a full path "
2669-
"that includes the driver filename at the end of it!"
2783+
"that includes the browser filename at the end of it!"
26702784
"\n(Will use default settings...)\n" % binary_location
26712785
)
26722786
# Example of a valid binary location path - MacOS:
@@ -2675,6 +2789,34 @@ def get_driver(
26752789
else:
26762790
binary_name = binary_location.split("/")[-1].split("\\")[-1]
26772791
valid_names = get_valid_binary_names_for_browser(browser_name)
2792+
if binary_name == "Google Chrome for Testing.app":
2793+
binary_name = "Google Chrome for Testing"
2794+
binary_location += "/Contents/MacOS/Google Chrome for Testing"
2795+
elif binary_name in ["chrome-mac-arm64", "chrome-mac-x64"]:
2796+
binary_name = "Google Chrome for Testing"
2797+
binary_location += "/Google Chrome for Testing.app"
2798+
binary_location += "/Contents/MacOS/Google Chrome for Testing"
2799+
elif binary_name == "chrome-linux64":
2800+
binary_name = "chrome"
2801+
binary_location += "/chrome"
2802+
elif binary_name in ["chrome-win32", "chrome-win64"]:
2803+
binary_name = "chrome.exe"
2804+
binary_location += "\\chrome.exe"
2805+
elif binary_name in [
2806+
"chrome-headless-shell-mac-arm64",
2807+
"chrome-headless-shell-mac-x64",
2808+
]:
2809+
binary_name = "chrome-headless-shell"
2810+
binary_location += "/chrome-headless-shell"
2811+
elif binary_name == "chrome-headless-shell-linux64":
2812+
binary_name = "chrome-headless-shell"
2813+
binary_location += "/chrome-headless-shell"
2814+
elif binary_name in [
2815+
"chrome-headless-shell-win32",
2816+
"chrome-headless-shell-win64",
2817+
]:
2818+
binary_name = "chrome-headless-shell.exe"
2819+
binary_location += "\\chrome-headless-shell.exe"
26782820
if binary_name not in valid_names:
26792821
log_d(
26802822
"\nWarning: The Chromium binary specified is NOT valid!"
@@ -2683,6 +2825,8 @@ def get_driver(
26832825
"" % (binary_name, valid_names)
26842826
)
26852827
binary_location = None
2828+
elif binary_location.lower() == "chs":
2829+
headless = True
26862830
if (uc_cdp_events or uc_subprocess) and not undetectable:
26872831
undetectable = True
26882832
if mobile_emulator and not user_agent:

seleniumbase/plugins/driver_manager.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,34 @@ def Driver(
530530
break
531531
count += 1
532532
user_agent = agent
533+
found_bl = None
534+
if binary_location is None and "--binary-location" in arg_join:
535+
count = 0
536+
for arg in sys_argv:
537+
if arg.startswith("--binary-location="):
538+
found_bl = arg.split("--binary-location=")[1]
539+
break
540+
elif arg == "--binary-location" and len(sys_argv) > count + 1:
541+
found_bl = sys_argv[count + 1]
542+
if found_bl.startswith("-"):
543+
found_bl = None
544+
break
545+
count += 1
546+
if found_bl:
547+
binary_location = found_bl
548+
if binary_location is None and "--bl=" in arg_join:
549+
for arg in sys_argv:
550+
if arg.startswith("--bl="):
551+
binary_location = arg.split("--bl=")[1]
552+
break
553+
if (
554+
binary_location
555+
and binary_location.lower() == "chs"
556+
and browser == "chrome"
557+
):
558+
headless = True
559+
headless1 = False
560+
headless2 = False
533561
recorder_mode = False
534562
if recorder_ext:
535563
recorder_mode = True

seleniumbase/plugins/pytest_plugin.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,7 @@ def pytest_addoption(parser):
656656
parser.addoption(
657657
"--binary_location",
658658
"--binary-location",
659+
"--bl",
659660
action="store",
660661
dest="binary_location",
661662
default=None,
@@ -1574,6 +1575,14 @@ def pytest_configure(config):
15741575
sb_config.extension_dir = config.getoption("extension_dir")
15751576
sb_config.disable_features = config.getoption("disable_features")
15761577
sb_config.binary_location = config.getoption("binary_location")
1578+
if (
1579+
sb_config.binary_location
1580+
and sb_config.binary_location.lower() == "chs"
1581+
and sb_config.browser == "chrome"
1582+
):
1583+
sb_config.headless = True
1584+
sb_config.headless1 = False
1585+
sb_config.headless2 = False
15771586
sb_config.driver_version = config.getoption("driver_version")
15781587
sb_config.page_load_strategy = config.getoption("page_load_strategy")
15791588
sb_config.with_testing_base = config.getoption("with_testing_base")

seleniumbase/plugins/sb_manager.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,34 @@ def SB(
568568
break
569569
count += 1
570570
user_agent = agent
571+
found_bl = None
572+
if binary_location is None and "--binary-location" in arg_join:
573+
count = 0
574+
for arg in sys_argv:
575+
if arg.startswith("--binary-location="):
576+
found_bl = arg.split("--binary-location=")[1]
577+
break
578+
elif arg == "--binary-location" and len(sys_argv) > count + 1:
579+
found_bl = sys_argv[count + 1]
580+
if found_bl.startswith("-"):
581+
found_bl = None
582+
break
583+
count += 1
584+
if found_bl:
585+
binary_location = found_bl
586+
if binary_location is None and "--bl=" in arg_join:
587+
for arg in sys_argv:
588+
if arg.startswith("--bl="):
589+
binary_location = arg.split("--bl=")[1]
590+
break
591+
if (
592+
binary_location
593+
and binary_location.lower() == "chs"
594+
and browser == "chrome"
595+
):
596+
headless = True
597+
headless1 = False
598+
headless2 = False
571599
recorder_mode = False
572600
if recorder_ext:
573601
recorder_mode = True

seleniumbase/plugins/selenium_plugin.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,7 @@ def options(self, parser, env):
397397
parser.addoption(
398398
"--binary_location",
399399
"--binary-location",
400+
"--bl",
400401
action="store",
401402
dest="binary_location",
402403
default=None,
@@ -1202,6 +1203,14 @@ def beforeTest(self, test):
12021203
test.test.extension_dir = self.options.extension_dir
12031204
test.test.disable_features = self.options.disable_features
12041205
test.test.binary_location = self.options.binary_location
1206+
if (
1207+
test.test.binary_location
1208+
and test.test.binary_location.lower() == "chs"
1209+
and test.test.browser == "chrome"
1210+
):
1211+
test.test.headless = True
1212+
test.test.headless1 = False
1213+
test.test.headless2 = False
12051214
test.test.driver_version = self.options.driver_version
12061215
test.test.page_load_strategy = self.options.page_load_strategy
12071216
test.test.chromium_arg = self.options.chromium_arg

0 commit comments

Comments
 (0)