Rspec with headless Chrome/Chromium on Alpine Linux
Asked Answered
A

2

17

On Alpine 3.10.1, I'm trying to run RSpec with headless_chrome.

 config.before(:each, type: :system, js: true) do
    driven_by :selenium, using: :headless_chrome
  end

I have installed capybara and webdrivers.

Since I haven't found a way to install Chrome on Alpine, I have tried with Chromium (76.0.3809.87-r0). But, when I run the spec, it doesn't find the driver.

ChildProcess::LaunchError: No such file or directory - /root/.webdrivers/chromedriver

I have tried also to install chromium-chromedriver directly via apk but the outcome has been the same.

Is there a way to install Chrome on Alpine or to use Chromium with Capybara?

Anticline answered 16/8, 2019 at 22:24 Comment(2)
I'm facing this too — tests previously running successfully with Chromium installed under /usr/bin/chromium-browser. Switching to webdrivers/selenium-webdriver gives the error you're seeing. Even with WD_CHROME_PATH set. The file chromedriver is actually there any the Jenkins user has permiissions for it too.Kmeson
We had this kind of errors in the past. Not sure it can help you but here is an extract of part of our patch for Linux platforms: "Selenium::WebDriver::Chrome.path = (which chromium.presence || which chromium-browser).chomp"Yale
P
5

There are three things necessary to get this working:

  1. Use selenium-webdriver instead of webdrivers
  2. Install chromium, chromium-chromedriver and selenium on your Docker image
  3. Configure a Capybara driver

Details below.

Use selenium-webdriver instead of webdrivers

If you happen to be using the webdrivers gem in your Gemfile, replace it with selenium-webdriver.

Install chromium, chromium-chromedriver and selenium on your Docker image

Alter your Dockerfile so that the following packages are being installed:

chromium chromium-chromedriver python3 python3-dev py3-pip

Then, after that, include the line RUN pip3 install -U selenium.

Below is a full sample Dockerfile.

FROM ruby:2.7.2-alpine AS builder

RUN apk add --no-cache \
    build-base libffi-dev \
    nodejs yarn tzdata \
    postgresql-dev postgresql-client zlib-dev libxml2-dev libxslt-dev readline-dev bash \
    #
    # For testing
    chromium chromium-chromedriver python3 python3-dev py3-pip \
    #
    # Nice-to-haves
    git vim \
    #
    # Fixes watch file issues with things like HMR
    libnotify-dev

RUN pip3 install -U selenium

FROM builder AS development

# Add the current apps files into docker image
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

# Install any extra dependencies via Aptfile - These are installed on Heroku
# COPY Aptfile /usr/src/app/Aptfile
# RUN apk add --update $(cat /usr/src/app/Aptfile | xargs)

ENV PATH /usr/src/app/bin:$PATH

# Install latest bundler
RUN bundle config --global silence_root_warning 1

EXPOSE 3000
CMD ["rails", "server", "-b", "0.0.0.0", "-p", "3000"]

FROM development AS production

COPY Gemfile /usr/src/app
COPY .ruby-version /usr/src/app
COPY Gemfile.lock /usr/src/app

COPY package.json /usr/src/app
COPY yarn.lock /usr/src/app

# Install Ruby Gems
RUN bundle config set deployment 'true'
RUN bundle config set without 'development:test'
RUN bundle check || bundle install --jobs=$(nproc)

# Install Yarn Libraries
RUN yarn install --check-files

# Copy the rest of the app
COPY . /usr/src/app

# Precompile the assets
RUN RAILS_SERVE_STATIC_FILES=enabled SECRET_KEY_BASE=secret-key-base RAILS_ENV=production RACK_ENV=production NODE_ENV=production bundle exec rake assets:precompile

# Precompile Bootsnap
run RAILS_SERVE_STATIC_FILES=enabled SECRET_KEY_BASE=secret-key-base RAILS_ENV=production RACK_ENV=production NODE_ENV=production bundle exec bootsnap precompile --gemfile app/ lib/

Configure a Capybara driver

Put the following in spec/support/chrome.rb.

# spec/support/chrome.rb

driver = :selenium_chrome_headless

Capybara.server = :puma, {Silent: true}

Capybara.register_driver driver do |app|
  options = ::Selenium::WebDriver::Chrome::Options.new

  options.add_argument("--headless")
  options.add_argument("--no-sandbox")
  options.add_argument("--disable-dev-shm-usage")
  options.add_argument("--window-size=1400,1400")

  Capybara::Selenium::Driver.new(app, browser: :chrome, options: options)
end

Capybara.javascript_driver = driver

RSpec.configure do |config|
  config.before(:each, type: :system) do
    driven_by driver
  end
end

I wrote up a little more detail in a blog post I wrote on this topic.

Primitive answered 2/1, 2021 at 13:19 Comment(2)
Thanks for the detailed answer (and blog post)! I was wondering if you could discuss why selenium-webdriver vs webdrivers (as webdrivers was the pointed to from the deprecated chromedriver-helper)? Any substantial differences? I'm haven't done front-end testing in a long time, so just trying to get a better feel for the current situation as I try to jump back in. Thanks!Engadine
Sorry, I wish I could remember but I can't. My fuzzy memory is that webdrivers gave some kind of error or failed in some way like that.Primitive
C
3

Jason Swett's answer ultimately works but it has a lot of overhead. Most notably to get Capybara working on Alpine I didn't need to install Selenium or Python.

The simplest way I found to get RSpec + Capybara working on Alpine:

Dockerfile

FROM ruby:3.0.2-alpine

RUN apk --update add --no-cache chromium chromium-chromedriver

Gemfile

group :test do
  gem 'capybara' # 3.36.0 as of writing this
  gem 'selenium-webdriver' # 4.0.3 as of writing this
  # Make sure no other gems are installed, such as `webdrivers`
end

rails_helper.rb

Capybara.register_driver :headless_chromium do |app|
  options = Selenium::WebDriver::Chrome::Options.new
  options.add_argument("--headless")
  options.add_argument("--no-sandbox")
  options.add_argument("--disable-dev-shm-usage")
  options.add_argument("--window-size=1280,900")
  Capybara::Selenium::Driver.new(app, browser: :chrome, capabilities: options)
end
Capybara.javascript_driver = :headless_chromium
Cacography answered 22/11, 2021 at 14:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.