The Wayback Machine - https://web.archive.org/web/20200920004311/https://github.com/seleniumbase/SeleniumBase/issues/535
Skip to content
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

`--cap-file=CAP_FILE` only works with tests that run on Selenium Grid #535

Open
aklajnert opened this issue Apr 1, 2020 · 13 comments
Open

`--cap-file=CAP_FILE` only works with tests that run on Selenium Grid #535

aklajnert opened this issue Apr 1, 2020 · 13 comments
Labels

Comments

@aklajnert
Copy link
Contributor

@aklajnert aklajnert commented Apr 1, 2020

Currently, SeleniumBase has cap_file option, that doesn't seem to work.

What I want to achieve is to add {'goog:loggingPrefs': {'browser': 'ALL'}}. Unfortunately, the only way I achieved that is by ugly monkey-patching around the webdriver.

I've tried to set cap_file to file with something like below, but it didn't work. Actually nothing happened. There was no difference in capabilities with or without the file.

My example cap_file:

capabilities  = desired_cap = desired_capabilities = {'goog:loggingPrefs': {'browser': 'ALL'}}

I've debugged the sources and it seems that the get_local_driver() method doesn't use the file at all.

@tcw0nw
Copy link

@tcw0nw tcw0nw commented Apr 1, 2020

same question
capabilities = { 'browserName': 'chrome', 'tz': 'Asia/Harbin', 'build': "build_%s" % time.strftime("%Y-%m-%d_%H-%M-%S", time.gmtime()), 'name': "build_%s" % time.strftime("%Y-%m-%d_%H-%M-%S", time.gmtime()), 'idleTimeout': 90, }

`node = <_ast.BinOp object at 0x10719c890>

def _convert_num(node):
    if isinstance(node, Constant):
        if isinstance(node.value, (int, float, complex)):
            return node.value
    elif isinstance(node, Num):
        return node.n
  raise ValueError('malformed node or string: ' + repr(node))

E ValueError: malformed node or string: <_ast.BinOp object at 0x10719c890>`

@mdmintz
Copy link
Member

@mdmintz mdmintz commented Apr 2, 2020

@aklajnert @tcw0nw What run commands are you using? If running locally, you must use a Selenium Grid, and you can start one up with two lines on the command line:

seleniumbase grid-hub start
seleniumbase grid-node start

Now you can run something like this from the examples/ folder:

pytest basic_test.py --server=127.0.0.1 --cap-file=capabilities/sample_cap_file_BS.py
=============================================== test session starts ================================================
platform darwin -- Python 3.7.0, pytest-5.3.5, py-1.8.0, pluggy-0.13.1
rootdir: /Users/michael/github/SeleniumBase, inifile: pytest.ini
plugins: timeout-1.3.4, html-2.0.1, rerunfailures-9.0, xdist-1.31.0, ordering-0.6, forked-1.1.3, metadata-1.8.0, cov-2.8.1, seleniumbase-1.36.9
collected 1 item                                                                                                   

basic_test.py Starting ChromeDriver 2.44.609545 (c2f88692e98ce7233d2df7c724465ecacfe74df5) on port 44953
Only local connections are allowed.
.

================================================ 1 passed in 5.20s
@aklajnert
Copy link
Contributor Author

@aklajnert aklajnert commented Apr 2, 2020

@mdmintz why the selenium grid is required here? The local driver should also have the ability to override the capabilities (which I did with an ugly hack).
Maybe allowing to specify a JSON file with capability overrides would be a good idea?

Here's my hack in case someone needs it:

from selenium.webdriver.chrome.options import Options


to_capabilities = Options.to_capabilities


def new_to_capabilities(self):
    capabilities = to_capabilities(self)
    capabilities["goog:loggingPrefs"] = {"browser": "ALL"}
    return capabilities


Options.to_capabilities = new_to_capabilities

I would expect SeleniumBase to just pass desired_capabilities to the WebDriver constructor, which does the update() on capabilities.

@tcw0nw
Copy link

@tcw0nw tcw0nw commented Apr 2, 2020

@mdmintz why the selenium grid is required here? The local driver should also have the ability to override the capabilities (which I did with an ugly hack).
Maybe allowing to specify a JSON file with capability overrides would be a good idea?

Here's my hack in case someone needs it:

from selenium.webdriver.chrome.options import Options


to_capabilities = Options.to_capabilities


def new_to_capabilities(self):
    capabilities = to_capabilities(self)
    capabilities["goog:loggingPrefs"] = {"browser": "ALL"}
    return capabilities


Options.to_capabilities = new_to_capabilities

I would expect SeleniumBase to just pass desired_capabilities to the WebDriver constructor, which does the update() on capabilities.

Can you see the complete code?

@aklajnert
Copy link
Contributor Author

@aklajnert aklajnert commented Apr 2, 2020

@tcw0nw what do you mean?

@mdmintz
Copy link
Member

@mdmintz mdmintz commented Apr 3, 2020

@aklajnert
desired_capabilities is natively built into webdriver.Remote(), example:

webdriver.Remote(command_executor, desired_capabilities, browser_profile)

But it is not built natively into webdriver.Chrome(), webdriver.Firefox(), etc...
And if you try adding it, you may override important SeleniumBase options, which you can already set from the command line. But there are no issues with using webdriver.Remote(), and that's where the capabilities come in. But Remote does require a Selenium Grid, and that's not an issue with SeleniumBase's built-in Grid management tools, such as seleniumbase grid-hub start and seleniumbase grid-node start.

@aklajnert
Copy link
Contributor Author

@aklajnert aklajnert commented Apr 3, 2020

@mdmintz are you sure that didn't change? Here's a fragment of my site-packages\selenium\webdriver\chrome\webdriver.py file:

class WebDriver(RemoteWebDriver):
    """
    Controls the ChromeDriver and allows you to drive the browser.

    You will need to download the ChromeDriver executable from
    http://chromedriver.storage.googleapis.com/index.html
    """

    def __init__(self, executable_path="chromedriver", port=0,
                 options=None, service_args=None,
                 desired_capabilities=None, service_log_path=None,
                 chrome_options=None, keep_alive=True):
        ...

As you see, the __init__() method has desired_capabilities option. I'm able to modify it (using the hack I shown above), the capabilities are set properly. And I'm running my tests with simple pytest command.

@mdmintz
Copy link
Member

@mdmintz mdmintz commented Apr 3, 2020

@aklajnert Thank you. I'll look into it more and see what I can do. That does appear to be using RemoteWebDriver, and if you've explored Selenium 4 at all (beta is available), you'll see that DeprecationWarning: executable_path has been deprecated, please pass in a Service object would result from using that, and I'm already looking ahead to the future for a seamless transition when it arrives. Given that I'm probably going to be changing this code (from browser_launcher.py) when Selenium 4 arrives, and given that they are still finalizing changes, I'm better off waiting until that's out (hopefully soon) so that I don't need to be making all these changes twice.

@aklajnert
Copy link
Contributor Author

@aklajnert aklajnert commented Apr 3, 2020

@mdmintz got it, that's reasonable. For now, I'm good with the ugly monkey-patching.

@mdmintz mdmintz changed the title Setting capabilities with `cap_file` doesn't work Setting capabilities with `--cap_file=CAP_FILE` only works for `--browser=remote` Apr 16, 2020
@mdmintz mdmintz changed the title Setting capabilities with `--cap_file=CAP_FILE` only works for `--browser=remote` Setting capabilities with `--cap_file=CAPABILITIES_FILE` only works for `--browser=remote` Apr 16, 2020
@mdmintz mdmintz changed the title Setting capabilities with `--cap_file=CAPABILITIES_FILE` only works for `--browser=remote` Setting capabilities with `--cap_file=CAP_FILE` only works with `--browser=remote` Apr 16, 2020
@mdmintz
Copy link
Member

@mdmintz mdmintz commented Apr 16, 2020

I changed the title since this works correctly when using a remote Selenium Grid such as Sauce Labs or Browserstack.
It'll also work if you use a local Selenium grid:

seleniumbase grid-hub start
seleniumbase grid-node start
pytest MY_TEST.py --server="127.0.0.1" --browser=remote --cap-file=CAP_FILE
@mdmintz mdmintz added the enhancement label Apr 18, 2020
@mdmintz mdmintz changed the title Setting capabilities with `--cap_file=CAP_FILE` only works with `--browser=remote` `--cap-file=CAP_FILE` only works with tests that run on Selenium Grid Apr 22, 2020
@q30
Copy link

@q30 q30 commented Jun 8, 2020

Can self.get_new_driver be used for this purpose? It seems to allow you to provide cap_file in its params. However I wasn't able to get it to work correctly myself. It opens a new browser for me but my test doesn't make use of it and continue to open another browser instance for running tests.

@mdmintz
Copy link
Member

@mdmintz mdmintz commented Jun 8, 2020

@q30 The cap_file still needs a Selenium Grid to process the desired capabilities right now. Changing this is on hold until Selenium 4 is officially released because that's going to simplify a lot of things related to this. Right now, SeleniumBase includes multiple command-line options that will let you set things without the cap file. But if you need the cap_file (which was orginally made to make it easier to use remote Selenium Grids like BrowserStack and Sauce Labs) then you can still easily spin up your own Selenium Grid with: seleniumbase grid-hub start and seleniumbase grid-node start.

@q30
Copy link

@q30 q30 commented Jun 8, 2020

Thank you @mdmintz! This helps.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
4 participants
You can’t perform that action at this time.