Updated: Capybara: Running tests with headless Chrome

Posted . Visible to the public. Auto-destruct in 50 days

Updated for recent versions of Chrome, which do not have a "remote debugging address" and only listen on localhost.

Changes

  • [Headless Chrome](https://developers.google.com/web/updates/2017/04/headless-chrome) is a way to run the Chrome browser without a visible window.
  • Configuring Capybara
  • ====================
  • Configure the Capybara driver like this:
  • ```ruby
  • Capybara.register_driver :selenium do |app|
  • options = Selenium::WebDriver::Chrome::Options.new
  • + options.add_argument('--disable-infobars')
  • + options.add_emulation(device_metrics: { width: 1280, height: 960, touch: false })
  • unless ENV.key?('NO_HEADLESS')
  • options.add_argument('--headless')
  • options.add_argument('--disable-gpu')
  • end
  • - if ENV.key?('CI')
  • + if ENV.key?('CI') # Also when in Docker
  • options.add_argument('--no-sandbox')
  • options.add_argument('--disable-dev-shm-usage')
  • end
  • if ENV.key?('REMOTE_DEBUGGING')
  • - options.add_argument('--remote-debugging-address=0.0.0.0')
  • - options.add_argument('--remote-debugging-port=9222')
  • + options.add_argument('--remote-debugging-port=9223')
  • end
  • - options.add_argument('--disable-infobars')
  • - options.add_emulation(device_metrics: { width: 1280, height: 960, touch: false })
  • Capybara::Selenium::Driver.new(app, browser: :chrome, options: options)
  • end
  • Selenium::WebDriver.logger.level = :error
  • ```
  • ## Headless Chrome in legacy Capybara 1 projects
  • If you're working on a legacy project with Capybara version 1.x, the code below should do:
  • ```ruby
  • Capybara.register_driver :selenium do |app|
  • args = []
  • args << '--headless' unless ENV.key?('NO_HEADLESS')
  • args << '--disable-infobars'
  • args << '--window-size=1280,960'
  • Capybara::Selenium::Driver.new(app, browser: :chrome, args: args)
  • end
  • ```
  • Looking at the hidden browser
  • =============================
  • Option 1: Run without headless
  • -------------------------------
  • -You can call your tests with `NO_HEADLESS=1 bundle exec cucumber` to see the Chrome window for this test run.
  • +You can call your tests with `NO_HEADLESS=1 bundle exec cucumber` to see the Chrome window for this test run. (This will not work when your Chrome is running inside Docker – in that case see option 2.)
  • You might want to define a bash alias `alias nh='NO_HEADLESS=1'` to shorten this command to `nh bundle exec cucumber`.
  • Option 2: Remote debugging
  • --------------------------
  • -In case your Chrome is running within a docker container, the remote debugging option helps you to connect your Chrome inside the docker image with a Chrome on your host system.
  • +With remote debugging, you can access a Docker Chrome from the host system.
  • -Here is an example for a docker container started with `docker-compose`:
  • +Here is an example for a Docker container started with `docker-compose`:
  • -1. Start the docker image with an exposed port `docker-compose run --publish 9222:9222 some-app bash`
  • -3. Go to `chrome://inspect/`, check `Discover network targets`, follow `Configure...` next to the `Discover network targets` and add `localhost:9222` in the `Target discovery settings`
  • -2. Start you integration test e.g. `REMOTE_DEBUGGING=true bundle exec rspec spec/system/some_spec.rb` with a debugger set
  • -4. You should now be able to connect to chrome within your docker image
  • +1. Start the Docker container: `docker-compose run --publish 9222:9222 $service bash` (mapping the local port 9222 into that container, and starting a shell)
  • +2. Capybara will instruct its instance of Chrome to open the remote debugging port. Unfortunately, Chrome will only listen on localhost. You need to make the debugging port available to the (Docker) network: `socat TCP4-LISTEN:9222,fork TCP4:127.0.0.1:9223` (if missing, install with `sudo apt install socat`)
  • +2. Start you integration test e.g. `REMOTE_DEBUGGING=1 bundle exec rspec spec/system/some_spec.rb` with a debugger set
  • +0. Open <chrome://inspect/>. It should list the test Chrome under "Remote target". (Ensure "Discover network targets" is enabled and "localhost:9222" is registered behind the "Configure…" button.)
  • > [NOTE]
  • > Remote debugging does not work well if you change your selenium driver between features (e.g. from a mobile device emulation back to a desktop browser). Therefore it makes more sense to run only single features / specs with REMOTE_DEBUGGING enabled.
  • ![Image](/makandra/492109/attachments/31439)
Dominik Schöler
License
Source code in this card is licensed under the MIT License.
Posted by Dominik Schöler to makandra dev (2025-01-08 14:33)