I’ve been using Capybara-WebKit for a long time but while switching from CircleCI 1.0 to CircleCI 2.0 I had some problems to use it on the CI.

This triggered to try Chrome Headless with Selenium Webdriver. I will show you how to configure Circle CI 2.0 and your Ruby on Rails project to use capybara/selenium/chrome headless together.

Add capybara and selenium-webdriver

Let’s add capybara and selenium-webdriver gems to Gemfile :

# Gemfile

group :development, :test do

gem 'capybara'

gem 'selenium-webdriver'

end

and run bundle install .

If you already had the gems in your Gemfile then ensure you have latest version with bundle update capybara selenium-webdriver .

If you want to make sure Capybara feature specs will work on your development machine:

$ brew install chromedriver

If your feature specs fail then upgrade the driver because you may have installed old one.

$ brew upgrade chromedriver

Configure Capybara

Add config file for Capybara:

# spec/support/config/capybara.rb

JS_DRIVER = :selenium_chrome_headless



Capybara.default_driver = :rack_test

Capybara.javascript_driver = JS_DRIVER

Capybara.default_max_wait_time = 2



RSpec.configure do |config|

config.before(:each) do |example|

Capybara.current_driver = JS_DRIVER if example.metadata[:js]

Capybara.current_driver = :selenium if example.metadata[:selenium]

Capybara.current_driver = :selenium_chrome if example.metadata[:selenium_chrome]

end



config.after(:each) do

Capybara.use_default_driver

end

end

Ensure you load config files from spec/support directory:

# spec/rails_helper.rb



# The following line is provided for convenience purposes. It has the downside

# of increasing the boot-up time by auto-requiring all files in the support

# directory. Alternatively, in the individual `*_spec.rb` files, manually

# require only the support files necessary.

Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }

Example feature spec

We can create example feature spec to test if everything works:

# spec/features/home_spec.rb

feature 'Homepage Features' do

before { visit root_path }



# it won't run js code but it is fast

it do

expect(page).to have_content 'Hello World'

end



# it will run js code

it '', :js do

expect(page).to have_content 'Hello World'

end



# it will open Firefox

# remove x from xit to run the test in Firefox on your machine to preview

xit '', :selenium do

expect(page).to have_content 'Hello World'

end



# it will open Chrome

# remove x from xit to run the test in Chrome on your machine to preview

xit '', :selenium_chrome do

expect(page).to have_content 'Hello World'

end

end

And run tests on your development machine with bin/rspec spec/features/home_spec.rb or bundle exec rspec spec/features/home_spec.rb .

Here is example .circleci/config.yml :

# .circleci/config.yml

version: 2

jobs:

build:

parallelism: 1

working_directory: ~/project-name

docker:

# this is important to use proper image with browsers support

- image: circleci/ruby:2.5.0-node-browsers

environment:

PGHOST: 127.0.0.1

PGUSER: project-name

RAILS_ENV: test

- image: circleci/postgres:9.4.12-alpine

environment:

POSTGRES_DB: project-name_test

POSTGRES_PASSWORD: ""

POSTGRES_USER: project-name

- image: redis:3.2.7

steps:

- checkout



# Restore bundle cache

- type: cache-restore

# remove space between { {

key: project-name-{ { checksum "Gemfile.lock" }}



# Bundle install dependencies

- run: bundle install --path vendor/bundle



# Store bundle cache

- type: cache-save

# remove space between { {

key: project-name-{ { checksum "Gemfile.lock" }}

paths:

- vendor/bundle



# Prepare .env, useful if you use dotenv gem

- run: cp .env.example .env



# Database setup

- run: bundle exec rake db:create

- run: bundle exec rake db:schema:load



# Run rspec in parallel

- type: shell

command: |

bundle exec rspec --profile 10 \

--format RspecJunitFormatter \

--out /tmp/test-results/rspec.xml \

--format progress



# Save artifacts

- type: store_test_results

path: /tmp/test-results

Speed up your tests with Circle CI parallelisation

If your feature specs are very long you can save some time by running multiple parallel CI nodes. For instance set it to 6 in .circleci/config.yml and use dynamic RSpec specs allocation across CI nodes with knapsack_pro gem and Queue Mode to get optimal test suite split to save as much time as possible.

# .circleci/config.yml

jobs:

build:

parallelism: 6



steps:

# some tests that are not balanced and executed only on first CI node

- run: case $CIRCLE_NODE_INDEX in 0) npm test ;; esac



# auto-balancing CI build time execution to be flat and optimal (as fast as possible).

# Queue Mode does dynamic tests allocation so the previous not balanced run command won't

# create a bottleneck on the CI node

- run:

name: RSpec via knapsack_pro Queue Mode

command: |

# export word is important here!

export RAILS_ENV=test

bundle exec rake "knapsack_pro:queue:rspec[--format documentation]"

You can learn how RSpec test suite parallelisation works in 1 minute video.

Now you are good to push your code to a repository and see how your Capybara feature specs work with Chrome Headless on CircleCI 2.0.