diff --git a/examples/raw_parameter_script.py b/examples/raw_parameter_script.py index 981cdee1845..564bec390ae 100755 --- a/examples/raw_parameter_script.py +++ b/examples/raw_parameter_script.py @@ -42,6 +42,7 @@ sb.archive_logs = False sb.disable_csp = False sb.enable_sync = False + sb._reuse_session = False sb.visual_baseline = False sb.maximize_option = False sb.save_screenshot_after_test = False diff --git a/requirements.txt b/requirements.txt index cf8eeab67f9..251de642041 100755 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ pip>=19.3.1 -setuptools>=42.0.1 +setuptools>=42.0.2 setuptools-scm>=3.3.3 wheel>=0.33.6 six>=1.13.0 @@ -30,12 +30,13 @@ portalocker>=1.5.2 cryptography>=2.8 asn1crypto>=1.2.0 pyopenssl>=19.1.0 +pygments>=2.5.2 colorama>=0.4.1 pymysql>=0.9.3 pyotp>=2.3.0 boto>=2.49.0 cffi>=1.13.2 -tqdm>=4.39.0 +tqdm>=4.40.0 flake8>=3.7.9 -certifi>=2019.9.11 +certifi>=2019.11.28 pdfminer.six==20191110 diff --git a/seleniumbase/fixtures/base_case.py b/seleniumbase/fixtures/base_case.py index dd894f59916..d688998afa6 100755 --- a/seleniumbase/fixtures/base_case.py +++ b/seleniumbase/fixtures/base_case.py @@ -4122,6 +4122,7 @@ def setUp(self, masterqa_mode=False): self.extension_zip = sb_config.extension_zip self.extension_dir = sb_config.extension_dir self.maximize_option = sb_config.maximize_option + self._reuse_session = sb_config.reuse_session self.save_screenshot_after_test = sb_config.save_screenshot self.visual_baseline = sb_config.visual_baseline self.timeout_multiplier = sb_config.timeout_multiplier @@ -4192,21 +4193,50 @@ def setUp(self, masterqa_mode=False): if self.settings_file: settings_parser.set_settings(self.settings_file) - # Launch WebDriver for both Pytest and Nosetests - self.driver = self.get_new_driver(browser=self.browser, - headless=self.headless, - servername=self.servername, - port=self.port, - proxy=self.proxy_string, - agent=self.user_agent, - switch_to=True, - cap_file=self.cap_file, - disable_csp=self.disable_csp, - enable_sync=self.enable_sync, - user_data_dir=self.user_data_dir, - extension_zip=self.extension_zip, - extension_dir=self.extension_dir) - self._default_driver = self.driver + has_url = False + if self._reuse_session: + if not hasattr(sb_config, 'shared_driver'): + sb_config.shared_driver = None + if sb_config.shared_driver: + try: + self._default_driver = sb_config.shared_driver + self.driver = sb_config.shared_driver + self._drivers_list = [sb_config.shared_driver] + url = self.get_current_url() + if len(url) > 3: + has_url = True + except Exception: + pass + + if self._reuse_session and sb_config.shared_driver and has_url: + if self.start_page and len(self.start_page) >= 4: + if page_utils.is_valid_url(self.start_page): + self.open(self.start_page) + else: + new_start_page = "http://" + self.start_page + if page_utils.is_valid_url(new_start_page): + self.open(new_start_page) + else: + if self.get_current_url() != "data:,": + self.open("data:,") + else: + # Launch WebDriver for both Pytest and Nosetests + self.driver = self.get_new_driver(browser=self.browser, + headless=self.headless, + servername=self.servername, + port=self.port, + proxy=self.proxy_string, + agent=self.user_agent, + switch_to=True, + cap_file=self.cap_file, + disable_csp=self.disable_csp, + enable_sync=self.enable_sync, + user_data_dir=self.user_data_dir, + extension_zip=self.extension_zip, + extension_dir=self.extension_dir) + self._default_driver = self.driver + if self._reuse_session: + sb_config.shared_driver = self.driver def __set_last_page_screenshot(self): """ self.__last_page_screenshot is only for pytest html report logs @@ -4280,6 +4310,16 @@ def __add_pytest_html_extra(self): pass def __quit_all_drivers(self): + if self._reuse_session and sb_config.shared_driver: + if len(self._drivers_list) > 0: + sb_config.shared_driver = self._drivers_list[0] + self._default_driver = self._drivers_list[0] + self.switch_to_default_driver() + if len(self._drivers_list) > 1: + self._drivers_list = self._drivers_list[1:] + else: + self._drivers_list = [] + # Close all open browser windows self._drivers_list.reverse() # Last In, First Out for driver in self._drivers_list: @@ -4290,6 +4330,7 @@ def __quit_all_drivers(self): except Exception: pass self.driver = None + self._default_driver = None self._drivers_list = [] def tearDown(self): diff --git a/seleniumbase/plugins/pytest_plugin.py b/seleniumbase/plugins/pytest_plugin.py index 23cf352ca50..4f737ba0c1a 100644 --- a/seleniumbase/plugins/pytest_plugin.py +++ b/seleniumbase/plugins/pytest_plugin.py @@ -39,6 +39,7 @@ def pytest_addoption(parser): --verify_delay=SECONDS (The delay before MasterQA verification checks.) --disable_csp (This disables the Content Security Policy of websites.) --enable_sync (The option to enable "Chrome Sync".) + --reuse_session (The option to reuse the browser session between tests.) --maximize_window (The option to start with the web browser maximized.) --save_screenshot (The option to save a screenshot after each test.) --visual_baseline (Set the visual baseline for Visual/Layout tests.) @@ -292,6 +293,12 @@ def pytest_addoption(parser): dest='enable_sync', default=False, help="""Using this enables the "Chrome Sync" feature.""") + parser.addoption('--reuse_session', '--reuse-session', + action="store_true", + dest='reuse_session', + default=False, + help="""The option to reuse the selenium browser window + session between tests.""") parser.addoption('--maximize_window', '--maximize-window', '--maximize', '--fullscreen', action="store_true", @@ -360,12 +367,18 @@ def pytest_configure(config): sb_config.verify_delay = config.getoption('verify_delay') sb_config.disable_csp = config.getoption('disable_csp') sb_config.enable_sync = config.getoption('enable_sync') + sb_config.reuse_session = config.getoption('reuse_session') + sb_config.shared_driver = None # The default driver for session reuse sb_config.maximize_option = config.getoption('maximize_option') sb_config.save_screenshot = config.getoption('save_screenshot') sb_config.visual_baseline = config.getoption('visual_baseline') sb_config.timeout_multiplier = config.getoption('timeout_multiplier') sb_config.pytest_html_report = config.getoption('htmlpath') # --html=FILE + if sb_config.reuse_session: + if "".join(sys.argv) == "-c": # Can't "reuse_session" if multithreaded + sb_config.reuse_session = False + if "linux" in sys.platform and ( not sb_config.headed and not sb_config.headless): print( @@ -383,6 +396,16 @@ def pytest_configure(config): def pytest_unconfigure(): """ This runs after all tests have completed with pytest. """ proxy_helper.remove_proxy_zip_if_present() + if sb_config.reuse_session: + # Close the shared browser session + if sb_config.shared_driver: + try: + sb_config.shared_driver.quit() + except AttributeError: + pass + except Exception: + pass + sb_config.shared_driver = None def pytest_runtest_setup(): diff --git a/seleniumbase/plugins/selenium_plugin.py b/seleniumbase/plugins/selenium_plugin.py index 07856d77cc9..c7e335cd989 100755 --- a/seleniumbase/plugins/selenium_plugin.py +++ b/seleniumbase/plugins/selenium_plugin.py @@ -287,6 +287,7 @@ def beforeTest(self, test): test.test.visual_baseline = self.options.visual_baseline test.test.timeout_multiplier = self.options.timeout_multiplier test.test.use_grid = False + test.test._reuse_session = False if test.test.servername != "localhost": # Use Selenium Grid (Use --server=127.0.0.1 for localhost Grid) test.test.use_grid = True diff --git a/seleniumbase/utilities/selenium_grid/grid-hub b/seleniumbase/utilities/selenium_grid/grid-hub index a1ef23533c3..283e908febd 100755 --- a/seleniumbase/utilities/selenium_grid/grid-hub +++ b/seleniumbase/utilities/selenium_grid/grid-hub @@ -34,7 +34,7 @@ if [ "$GRID_HUB_VERBOSE_LOGS" == "True" ]; then fi WEBDRIVER_SERVER_JAR=${DIR}/selenium-server-standalone.jar -WEBDRIVER_HUB_PARAMS="-role hub -timeout 30 -browserTimeout 60 -port 4444" +WEBDRIVER_HUB_PARAMS="-role hub -timeout 180 -browserTimeout 75 -port 4444" WEBDRIVER_HUB_PIDFILE="/tmp/webdriver_hub.pid" if [ ! -f $WEBDRIVER_SERVER_JAR ]; then diff --git a/seleniumbase/utilities/selenium_grid/grid_hub.py b/seleniumbase/utilities/selenium_grid/grid_hub.py index 2703ef9089a..253ade18061 100755 --- a/seleniumbase/utilities/selenium_grid/grid_hub.py +++ b/seleniumbase/utilities/selenium_grid/grid_hub.py @@ -79,7 +79,7 @@ def main(): if grid_hub_command == "start" or grid_hub_command == "restart": shell_command = ( """java -jar %s/selenium-server-standalone.jar -role hub """ - """-timeout 30 -browserTimeout 60 -port 4444""" % dir_path) + """-timeout 180 -browserTimeout 75 -port 4444""" % dir_path) print("\nStarting Selenium-WebDriver Grid Hub...\n") print(shell_command) print("") diff --git a/seleniumbase/utilities/selenium_grid/start-grid-hub.bat b/seleniumbase/utilities/selenium_grid/start-grid-hub.bat index 70469894683..f2b81f55802 100755 --- a/seleniumbase/utilities/selenium_grid/start-grid-hub.bat +++ b/seleniumbase/utilities/selenium_grid/start-grid-hub.bat @@ -1 +1 @@ -java -jar selenium-server-standalone.jar -role hub -timeout 30 -browserTimeout 60 -port 4444 \ No newline at end of file +java -jar selenium-server-standalone.jar -role hub -timeout 180 -browserTimeout 75 -port 4444 \ No newline at end of file diff --git a/seleniumbase/utilities/selenium_grid/start-grid-hub.sh b/seleniumbase/utilities/selenium_grid/start-grid-hub.sh index ffa1f884b79..56a1f8066f7 100755 --- a/seleniumbase/utilities/selenium_grid/start-grid-hub.sh +++ b/seleniumbase/utilities/selenium_grid/start-grid-hub.sh @@ -1,2 +1,2 @@ #!/bin/bash -java -jar selenium-server-standalone.jar -role hub -timeout 30 -browserTimeout 60 -port 4444 \ No newline at end of file +java -jar selenium-server-standalone.jar -role hub -timeout 180 -browserTimeout 75 -port 4444 \ No newline at end of file diff --git a/setup.py b/setup.py index b87ab1fab43..ca160830b62 100755 --- a/setup.py +++ b/setup.py @@ -45,7 +45,7 @@ setup( name='seleniumbase', - version='1.33.8', + version='1.33.9', description='Fast, Easy, and Reliable Browser Automation & Testing.', long_description=long_description, long_description_content_type='text/markdown', @@ -113,14 +113,15 @@ 'cryptography>=2.8', 'asn1crypto>=1.2.0', 'pyopenssl>=19.1.0', + 'pygments>=2.5.2', 'colorama>=0.4.1', 'pymysql>=0.9.3', 'pyotp>=2.3.0', 'boto>=2.49.0', 'cffi>=1.13.2', - 'tqdm>=4.39.0', + 'tqdm>=4.40.0', 'flake8>=3.7.9', - 'certifi>=2019.9.11', + 'certifi>=2019.11.28', 'pdfminer.six==20191110', ], packages=[