Capybara: Running tests with headless Chrome

Headless Chrome Show archive.org snapshot is a way to run the Chrome browser without a visible window.

Configuring Capybara

Configure the Capybara driver like this:

Capybara.register_driver :selenium do |app|
  options = Selenium::WebDriver::Chrome::Options.new
  
  unless ENV.key?('NO_HEADLESS')
    options.add_argument('--headless')
    options.add_argument('--disable-gpu')
  end
  
  if ENV.key?('CI')
    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')  
  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:

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 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.

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
  2. 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
  3. 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

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

Henning Koch Over 3 years ago