Read more

How to enable Chromedriver logging

Arne Hartherz
September 26, 2019Software engineer at makandra GmbH

When using Chrome for Selenium tests, the chromedriver binary will be used to control Chrome. To debug problems that stem from Selenium's Chrome and/or Chromedriver, you might want to enable logging for the chromedriver itself. Here is how.

Option 1: Use Selenium::WebDriver::Service

Illustration UI/UX Design

UI/UX Design by makandra brand

We make sure that your target audience has the best possible experience with your digital product. You get:

  • Design tailored to your audience
  • Proven processes customized to your needs
  • An expert team of experienced designers
Read more Show archive.org snapshot

In your test setup, you may already have something like Capybara::Selenium::Driver.new(@app, browser: :chrome, options: ...), especially when passing options like device emulation.

Similar to options, simply add an extra key service and pass an instance of Selenium::WebDriver::Service like so:

service = ::Selenium::WebDriver::Chrome::Service.new(args: ['--verbose', '--log-path=/tmp/chromedriver.log'])
::Capybara::Selenium::Driver.new(@app, browser: :chrome, options: ..., service: service)

Note:

  • Version 3.x also supports passing the service arguments as driver_opts directly. However, this is deprecated and will be removed in version 4 of selenium-webdriver.
  • Version 5.x will drop support for passing the service options as hash. You might see a deprecation warning in version 4.x WARN Selenium [DEPRECATION] [:driver_opts] initializing Service class with :args using Hash is deprecated. Use :args parameter with an Array of String values instead..

Option 2: Connect tests to a manually started chromedriver

Warning

This does not work with selenium-webdriver > 4 anymore. You can pass in a specific port as attribute of the Selenium::WebDriver::Service, but the gem will use a different port if it is already in use.

If the above approach no longer works, or if you want to go bare metal, you can also start chromedriver yourself in a terminal on a custom port:

chromedriver --port=12345 --verbose --log-path=/tmp/chromedriver.log

Then configure Selenium to connect to that port. Like in option 1, you need to pass an extra key when creating your driver instance.

Capybara::Selenium::Driver.new(@app, browser: :chrome, options: ..., url: 'http://localhost:12345')

Note that you may omit the --log-path option to make chromedriver print to your terminal.

Example log output

    And I check "Some checkbox"                                                                                                            # spreewald-2.5.0/lib/spreewald/web_steps.rb:46
2020-01-02 00:00:03 INFO Selenium -> GET session/1230859ba100e7b2e5472cfb5bdf94c3/alert_text
2020-01-02 00:00:03 INFO Selenium <- {"sessionId":"1230859ba100e7b2e5472cfb5bdf94c3","status":27,"value":{"message":"no such alert\n  (Session info: chrome=84.0.4147.105)\n  (Driver info: chromedriver=84.0.4147.30 (48b3e868b4cc0aa7e8149519690b6f6949e110a8-refs/branch-heads/4147@{#310}),platform=Linux 5.4.0-42-generic x86_64)"}}
2020-01-02 00:00:03 WARN Selenium [DEPRECATION] Selenium::WebDriver::Error::NoAlertOpenError is deprecated. Use Selenium::WebDriver::Error::NoSuchAlertError (ensure the driver supports W3C WebDriver specification) instead.
2020-01-02 00:00:03 INFO Selenium -> POST session/1230859ba100e7b2e5472cfb5bdf94c3/se/log
2020-01-02 00:00:03 INFO Selenium    >>> http://127.0.0.1:9538/session/1230859ba100e7b2e5472cfb5bdf94c3/se/log | {"type":"browser"}
2020-01-02 00:00:03 DEBUG Selenium      > {"Accept"=>"application/json", "Content-Type"=>"application/json; charset=UTF-8", "User-Agent"=>"selenium/3.142.7 (ruby linux)", "Content-Length"=>"18"}
2020-01-02 00:00:03 INFO Selenium <- {"sessionId":"1230859ba100e7b2e5472cfb5bdf94c3","status":0,"value":[]}
2020-01-02 00:00:03 INFO Selenium -> POST session/1230859ba100e7b2e5472cfb5bdf94c3/elements
2020-01-02 00:00:03 INFO Selenium    >>> http://127.0.0.1:9538/session/1230859ba100e7b2e5472cfb5bdf94c3/elements | {"using":"xpath","value":".//input[((((./@type = 'submit') or (./@type = 'reset')) or (./@type = 'image')) or (./@type = 'button'))][((((./@id = 'Save') or (./@name = 'Save')) or (./@value = 'Save')) or (./@title = 'Save'))] | .//input[(./@type = 'image')][(./@alt = 'Save')] | .//button[((((((./@id = 'Save') or (./@name = 'Save')) or (./@value = 'Save')) or (./@title = 'Save')) or (normalize-space(string(.)) = 'Save')) or .//img[(./@alt = 'Save')])] | .//input[(./@type = 'image')][(./@alt = 'Save')]"}
2020-01-02 00:00:03 DEBUG Selenium      > {"Accept"=>"application/json", "Content-Type"=>"application/json; charset=UTF-8", "User-Agent"=>"selenium/3.142.7 (ruby linux)", "Content-Length"=>"506"}
2020-01-02 00:00:03 INFO Selenium <- {"sessionId":"1230859ba100e7b2e5472cfb5bdf94c3","status":0,"value":[{"ELEMENT":"0.2508372215483632-3"}]}
2020-01-02 00:00:03 INFO Selenium -> POST session/1230859ba100e7b2e5472cfb5bdf94c3/execute
2020-01-02 00:00:03 INFO Selenium    >>> http://127.0.0.1:9538/session/1230859ba100e7b2e5472cfb5bdf94c3/execute | {"script":"return arguments[0].matches(':disabled, select:disabled *')","args":[{"ELEMENT":"0.2508372215483632-3"}]}
2020-01-02 00:00:03 DEBUG Selenium      > {"Accept"=>"application/json", "Content-Type"=>"application/json; charset=UTF-8", "User-Agent"=>"selenium/3.142.7 (ruby linux)", "Content-Length"=>"116"}
2020-01-02 00:00:03 INFO Selenium <- {"sessionId":"1230859ba100e7b2e5472cfb5bdf94c3","status":0,"value":false}
2020-01-02 00:00:03 INFO Selenium -> POST session/1230859ba100e7b2e5472cfb5bdf94c3/element/0.2508372215483632-3/click
2020-01-02 00:00:03 INFO Selenium <- {"sessionId":"1230859ba100e7b2e5472cfb5bdf94c3","status":0,"value":null}
    And I press "Save"      

Further reading

Arne Hartherz
September 26, 2019Software engineer at makandra GmbH
Posted by Arne Hartherz to makandra dev (2019-09-26 09:44)