-
Notifications
You must be signed in to change notification settings - Fork 782
Selenium options string to object #1393
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
46ceebc
9a0ba84
4c60ba4
c29f2ad
d99ab2d
44de3bd
332cb88
12dcd1b
eefcc8b
3cec432
5e1eb78
435f08d
1ed9761
43746c5
0dffd43
0473aee
c14343f
575c5d4
ca55383
f3113d3
cd2ff5e
ac5b3c7
b6e6d38
27dc8c1
8f51376
0767097
5bc3e80
f668697
4456616
9b003d7
8cdd0c3
164a1ee
49aac86
ad58fe8
24702f2
7a1c51d
c19fb3f
bed6a6e
603f47a
4c39246
79b7c17
6364362
599e4c5
3f1973f
38e72eb
273626a
30abcf2
f9b1f5f
d725905
5f4f1ab
c1b4f65
27e0370
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| *** Settings *** | ||
| Suite Teardown Close All Browsers | ||
| Library ../resources/testlibs/get_selenium_options.py | ||
| Resource resource.robot | ||
| Documentation Creating test which would work on all browser is not possible. When testing with other | ||
| ... browser than Chrome it is OK that these test will fail. SeleniumLibrary CI is run with Chrome only | ||
| ... and therefore there is tests for Chrome only. | ||
|
|
||
| *** Test Cases *** | ||
| Chrome Browser With Selenium Options As String | ||
| [Documentation] | ||
| ... LOG 1:2 DEBUG GLOB: *"goog:chromeOptions"* | ||
| ... LOG 1:2 DEBUG GLOB: *args": ["--disable-dev-shm-usage"?* | ||
| Open Browser ${FRONT PAGE} ${BROWSER} remote_url=${REMOTE_URL} | ||
| ... desired_capabilities=${DESIRED_CAPABILITIES} options=add_argument("--disable-dev-shm-usage") | ||
|
|
||
| Chrome Browser With Selenium Options As String With Attirbute As True | ||
| [Documentation] | ||
| ... LOG 1:2 DEBUG GLOB: *"goog:chromeOptions"* | ||
| ... LOG 1:2 DEBUG GLOB: *args": ["--disable-dev-shm-usage"?* | ||
| ... LOG 1:2 DEBUG GLOB: *"--headless"* | ||
| Open Browser ${FRONT PAGE} ${BROWSER} remote_url=${REMOTE_URL} | ||
| ... desired_capabilities=${DESIRED_CAPABILITIES} options=add_argument ( "--disable-dev-shm-usage" ) ; headless = True | ||
|
|
||
| Chrome Browser With Selenium Options Object | ||
| [Documentation] | ||
| ... LOG 2:2 DEBUG GLOB: *"goog:chromeOptions"* | ||
| ... LOG 2:2 DEBUG GLOB: *args": ["--disable-dev-shm-usage"?* | ||
| ${options} = Get Chrome Options | ||
| Open Browser ${FRONT PAGE} ${BROWSER} remote_url=${REMOTE_URL} | ||
| ... desired_capabilities=${DESIRED_CAPABILITIES} options=${options} | ||
|
|
||
| Chrome Browser With Selenium Options Invalid Method | ||
| Run Keyword And Expect Error AttributeError: 'Options' object has no attribute 'not_here_method' | ||
| ... Open Browser ${FRONT PAGE} ${BROWSER} remote_url=${REMOTE_URL} | ||
| ... desired_capabilities=${DESIRED_CAPABILITIES} options=not_here_method("arg1") | ||
|
|
||
|
|
||
| Chrome Browser With Selenium Options Argument With Semicolon | ||
| [Documentation] | ||
| ... LOG 1:2 DEBUG GLOB: *"goog:chromeOptions"* | ||
| ... LOG 1:2 DEBUG GLOB: *["has;semicolon"* | ||
| Open Browser ${FRONT PAGE} ${BROWSER} remote_url=${REMOTE_URL} | ||
| ... desired_capabilities=${DESIRED_CAPABILITIES} options=add_argument("has;semicolon") |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| from selenium import webdriver | ||
|
|
||
|
|
||
| def get_chrome_options(): | ||
| options = webdriver.ChromeOptions() | ||
| options.add_argument('--disable-dev-shm-usage') | ||
| return options |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -58,7 +58,7 @@ def close_browser(self): | |
| @keyword | ||
| def open_browser(self, url, browser='firefox', alias=None, | ||
| remote_url=False, desired_capabilities=None, | ||
| ff_profile_dir=None, service_log_path=None): | ||
| ff_profile_dir=None, options=None, service_log_path=None): | ||
| """Opens a new browser instance to the given ``url``. | ||
|
|
||
| The ``browser`` argument specifies which browser to use, and the | ||
|
|
@@ -119,6 +119,71 @@ def open_browser(self, url, browser='firefox', alias=None, | |
| ``ff_profile_dir`` can also be instance of the | ||
| [https://seleniumhq.github.io/selenium/docs/api/py/webdriver_firefox/selenium.webdriver.firefox.firefox_profile.html?highlight=firefoxprofile#selenium.webdriver.firefox.firefox_profile.FirefoxProfile|selenium.webdriver.FirefoxProfile]. | ||
|
|
||
| Optional ``options`` argument allows to define browser specific | ||
| Selenium options. Example for Chrome, the ``options`` argument | ||
| allows defining the following | ||
| [https://seleniumhq.github.io/selenium/docs/api/py/webdriver_chrome/selenium.webdriver.chrome.options.html#selenium.webdriver.chrome.options.Options|methods and attributes] | ||
| and for Firefox these | ||
| [https://seleniumhq.github.io/selenium/docs/api/py/webdriver_firefox/selenium.webdriver.firefox.options.html?highlight=firefox#selenium.webdriver.firefox.options.Options|methods and attributes] | ||
| are available. Please note that not all browsers supported by the | ||
| SeleniumLibrary have Selenium options available. Therefore please | ||
| consult the Selenium documentation which browsers do support | ||
| the Selenium options. If ``browser`` argument is `android` then | ||
| [https://seleniumhq.github.io/selenium/docs/api/py/webdriver_chrome/selenium.webdriver.chrome.options.html#selenium.webdriver.chrome.options.Options|Chrome options] | ||
| is used. Selenium options are also supported, when ``remote_url`` | ||
| argument is used. | ||
|
|
||
| The SeleniumLibrary ``options`` argument accepts Selenium | ||
| options in two different formats: as a string and as Python object | ||
| which is an instance of the Selenium options class. | ||
|
|
||
| The string format allows to define Selenium options methods | ||
| or attributes and their arguments in Robot Framework test data. | ||
| The method and attributes names are case and space sensitive and | ||
| must match to the Selenium options methods and attributes names. | ||
| When defining a method, is must defined in similar way as in | ||
| python: method name, opening parenthesis, zero to many arguments | ||
| and closing parenthesis. If there is need to define multiple | ||
| arguments for a single method, arguments must be separated with | ||
| comma, just like in Python. Example: `add_argument("--headless")` | ||
| or `add_experimental_option("key", "value")`. Attributes are | ||
| defined in similar way as in Python: attribute name, equal sing | ||
| and attribute value. Example, `headless=True`. Multiple methods | ||
| and attributes must separated by a semicolon, example: | ||
| `add_argument("--headless");add_argument("--start-maximized")`. | ||
|
|
||
| Arguments allow defining Python data types and arguments are | ||
| evaluated by using Python | ||
| [https://docs.python.org/3/library/ast.html#ast.literal_eval|ast.literal_eval]. | ||
| Strings must be quoted with single or double quotes, example "value" | ||
| or 'value'. It is also possible define other Python builtin | ||
| data types, example `True` or `None`, by not using quotes | ||
| around the arguments. | ||
|
|
||
| The string format is space friendly and usually spaces do not alter | ||
| the defining the methods or attributes. There are two exceptions. | ||
| In some Robot Framework test data formats, two or more spaces are | ||
| considered as cell separator and instead of defining a single | ||
| argument, two or more arguments may be defined. Spaces in string | ||
| arguments are not removed and are left as is. Example | ||
| `add_argument ( "--headless" )` is same as | ||
| `add_argument("--headless")`. But `add_argument(" --headless ")` is | ||
| not same same as `add_argument ( "--headless" )`, because | ||
| spaces inside of quotes are not removed. | ||
|
|
||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. One difficulty with supporting a string formatted options is being backwards compatible over time or change the rules of how the string is formatted. You might try out the formatting with several users to see how it works for them.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That is a worry which I also have, but there are some safe guards. Calling the Selenium options is as much as possible backwards compatible, because behind the scenes it does a similar trick as the But there is a part that worries me and that is the importing options. First Selenium options import path may change or the options class name may change. In the past, that part has been quite stable and I have not seen any changes in the upcoming Selenium 4.0 release either. But who knows what future will bring. Also mobile devices, which are supported on the In any case, if the limitation in the string format is left as it is, it should be documented. Also we should remove the limitation when the Selenium options instance is passed in for mobile devices. That limitation should be easy to change, because now we support only two formats.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's impossible to make this fully future compatible because Selenium doesn't have a stable API for specifying options. The current approach to support specifying options like
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That is true. I still need to think should we do some extra for the mobile users. But perhaps easiest way is to:
Make alpha release and ask specially for people using mobile to take a look. |
||
| As last format ``options`` argument also support receiving | ||
| the Selenium options as Python class instance. In this case, the | ||
| instance is used as is and the SeleniumLibrary will not convert | ||
| the instance to other formats. | ||
| For example, if the following code return value is saved to | ||
| `${options}` variable in the Robot Framework data: | ||
| | options = webdriver.ChromeOptions() | ||
| | options.add_argument('--disable-dev-shm-usage') | ||
| | return options | ||
|
|
||
| Then the `${options}` variable can be used as argument to | ||
| ``options``. | ||
|
|
||
| Optional ``service_log_path`` argument defines the name of the | ||
| file where to write the browser driver logs. If the | ||
| ``service_log_path`` argument contain a marker ``{index}``, it | ||
|
|
@@ -142,6 +207,13 @@ def open_browser(self, url, browser='firefox', alias=None, | |
| | Should Be Equal | ${1_index} | ${4_index} | | | | | ||
| | Should Be Equal | ${2_index} | ${2} | | | | | ||
|
|
||
| Example when using | ||
| [https://seleniumhq.github.io/selenium/docs/api/py/webdriver_chrome/selenium.webdriver.chrome.options.html#selenium.webdriver.chrome.options.Options|Chrome options] | ||
| method: | ||
| | `Open Browser` | http://example.com | Chrome | options=add_argument("--disable-popup-blocking"); add_argument("--ignore-certificate-errors") | # Sting format | | ||
| | ${options} = | Get Options | | | # Selenium options instance | | ||
| | `Open Browser` | http://example.com | Chrome | options=${options 2} | | | ||
|
|
||
| If the provided configuration options are not enough, it is possible | ||
| to use `Create Webdriver` to customize browser initialization even | ||
| more. | ||
|
|
@@ -150,10 +222,10 @@ def open_browser(self, url, browser='firefox', alias=None, | |
| new in SeleniumLibrary 3.1. | ||
|
|
||
| Using ``alias`` to decide, is the new browser opened is new | ||
| in SeleniumLibrary 4.0. Also the ``service_log_path`` is new | ||
| in SeleniumLibrary 4.0. Support for ``ff_profile_dir`` accepting | ||
| instance of the `selenium.webdriver.FirefoxProfile` is new in | ||
| SeleniumLibrary 4.0. | ||
| in SeleniumLibrary 4.0. The ``options`` and ``service_log_path`` | ||
| are new in SeleniumLibrary 4.0. Support for ``ff_profile_dir`` | ||
| accepting instance of the `selenium.webdriver.FirefoxProfile` | ||
| is new in SeleniumLibrary 4.0. | ||
| """ | ||
| index = self.drivers.get_index(alias) | ||
| if index: | ||
|
|
@@ -163,19 +235,19 @@ def open_browser(self, url, browser='firefox', alias=None, | |
| return index | ||
| return self._make_new_browser(url, browser, alias, remote_url, | ||
| desired_capabilities, ff_profile_dir, | ||
| service_log_path) | ||
| options, service_log_path) | ||
|
|
||
| def _make_new_browser(self, url, browser='firefox', alias=None, | ||
| remote_url=False, desired_capabilities=None, | ||
| ff_profile_dir=None, service_log_path=None): | ||
| ff_profile_dir=None, options=None, service_log_path=None): | ||
| if is_truthy(remote_url): | ||
| self.info("Opening browser '%s' to base url '%s' through " | ||
| "remote server at '%s'." % (browser, url, remote_url)) | ||
| else: | ||
| self.info("Opening browser '%s' to base url '%s'." % (browser, url)) | ||
| driver = self._make_driver(browser, desired_capabilities, | ||
| ff_profile_dir, remote_url, | ||
| service_log_path) | ||
| options, service_log_path) | ||
| driver = self._wrap_event_firing_webdriver(driver) | ||
| try: | ||
| driver.get(url) | ||
|
|
@@ -504,11 +576,11 @@ def set_browser_implicit_wait(self, value): | |
| """ | ||
| self.driver.implicitly_wait(timestr_to_secs(value)) | ||
|
|
||
| def _make_driver(self, browser, desired_capabilities=None, | ||
| profile_dir=None, remote=None, service_log_path=None): | ||
| def _make_driver(self, browser, desired_capabilities=None, profile_dir=None, | ||
| remote=None, options=None, service_log_path=None): | ||
| driver = WebDriverCreator(self.log_dir).create_driver( | ||
| browser=browser, desired_capabilities=desired_capabilities, | ||
| remote_url=remote, profile_dir=profile_dir, service_log_path=service_log_path) | ||
| browser=browser, desired_capabilities=desired_capabilities, remote_url=remote, | ||
| profile_dir=profile_dir, options=options, service_log_path=service_log_path) | ||
| driver.set_script_timeout(self.ctx.timeout) | ||
| driver.implicitly_wait(self.ctx.implicit_wait) | ||
| if self.ctx.speed: | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just checking to make sure Firefox profile does not overlap or interfere with Firefox options ..? Read through the API docs and it looks like no they are mutually exclusive.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Those two partially overlap but generally Firefox options allows to do more. But they are not exclusive, one can define both and all should work fine. I did briefly tested the scenario and did not find problems. Although I did not dive deeply on the matter and I don't know if same setting is defined in both, which one has priority over other.