在Ruby / Capybara测试套件中使用selenium/standalone-chrome docker镜像

xmd2e60i  于 2023-05-17  发布在  Ruby
关注(0)|答案(3)|浏览(135)

我正在尝试用Ruby(没有Rails)编写一个Capybara测试套件。
我想在Docker容器中运行Ruby代码。

FROM ruby:2.7

RUN gem install bundler

COPY Gemfile Gemfile
COPY Gemfile.lock Gemfile.lock

RUN bundle install

COPY . .

CMD ["bundle", "exec", "rspec", "spec"]

我的测试需要一个无头版本的Chrome,这在Ruby镜像中是不可用的。我尝试创建一个docker-compose文件,以包含Ruby代码和一个无头Chrome映像。

version: '3.7'
networks:
  mynet:
services:
  admin:
    container_name: mrt-integ-tests
    image: cdluc3/mrt-integ-tests
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
    - type: bind
      source: ./config/test_config.yml
      target: /config/test_config.yml
    stdin_open: true
    tty: true
    networks:
      mynet:
    depends_on:
    - chrome
  chrome:
    container_name: chrome
    image: selenium/standalone-chrome
    ports:
    - published: 4444
      target: 4444
    networks:
      mynet:

这是我尝试创建我的Capybara会话的方式:

Capybara.register_driver :selenium_chrome do |app|
      args = ['--no-default-browser-check', '--start-maximized', '--headless', '--disable-dev-shm-usage']
      caps = Selenium::WebDriver::Remote::Capabilities.chrome("chromeOptions" => {"args" => args})

      Capybara::Selenium::Driver.new(
        app,
        browser: :remote,
        desired_capabilities: caps,
        url: "http://chrome:4444/wd/hub"
      )
    end
    @session = Capybara::Session.new(:selenium_chrome)

当我启动容器时,我看到以下错误。

chrome    | 05:39:44.350 INFO [GridLauncherV3.lambda$buildLaunchers$3] - Launching a standalone Selenium Server on port 4444
chrome    | 2020-06-04 05:39:44.420:INFO::main: Logging initialized @766ms to org.seleniumhq.jetty9.util.log.StdErrLog
chrome    | 05:39:44.920 INFO [WebDriverServlet.<init>] - Initialising WebDriverServlet
chrome    | 05:39:45.141 INFO [SeleniumServer.boot] - Selenium Server is up and running on port 4444
chrome    | 05:39:47.431 INFO [ActiveSessionFactory.apply] - Capabilities are: {
chrome    |   "browserName": "chrome",
chrome    |   "chromeOptions": {
chrome    |     "args": [
chrome    |       "--no-default-browser-check",
chrome    |       "--start-maximized",
chrome    |       "--headless",
chrome    |       "--disable-dev-shm-usage"
chrome    |     ]
chrome    |   },
chrome    |   "cssSelectorsEnabled": true,
chrome    |   "javascriptEnabled": true,
chrome    |   "nativeEvents": false,
chrome    |   "rotatable": false,
chrome    |   "takesScreenshot": false,
chrome    |   "version": ""
chrome    | }
chrome    | 05:39:47.435 INFO [ActiveSessionFactory.lambda$apply$11] - Matched factory org.openqa.selenium.grid.session.remote.ServicedSession$Factory (provider: org.openqa.selenium.chrome.ChromeDriverService)
chrome    | Starting ChromeDriver 83.0.4103.39 (ccbf011cb2d2b19b506d844400483861342c20cd-refs/branch-heads/4103@{#416}) on port 13554
chrome    | Only local connections are allowed.
chrome    | Please see https://chromedriver.chromium.org/security-considerations for suggestions on keeping ChromeDriver safe.
chrome    | ChromeDriver was started succ[e1s5s9f1u2l4l9y1.8
chrome    | 7.473][SEVERE]: bind() failed: Cannot assign requested address (99)
chrome    | 05:39:48.211 INFO [ProtocolHandshake.createSession] - Detected dialect: W3C
chrome    | 05:39:48.247 INFO [RemoteSession$Factory.lambda$performHandshake$0] - Started new session 1ed95304843a1d5ab904708d998710a0 (org.openqa.selenium.chrome.ChromeDriverService)

你有什么建议来解决这个错误?

y3bcpkx1

y3bcpkx11#

我这里有一个部分的解决方案。将 --whitelisted-ips 添加到我的浏览器选项中可以使我的测试正常运行。参见https://github.com/RobCherry/docker-chromedriver/issues/15

args = ['--no-default-browser-check', '--start-maximized', '--headless', '--disable-dev-shm-usage']

args = ['--no-default-browser-check', '--start-maximized', '--headless', '--disable-dev-shm-usage', '--whitelisted-ips']

有趣的是,chrome容器中仍然会生成以下错误。

[1591286416.104][SEVERE]: bind() failed: Cannot assign requested address (99)
j8yoct9x

j8yoct9x2#

您需要为chromedriver可执行文件设置whitelisted-ips参数。你可以通过为docker chrome-node image设置env JAVA_OPTS来实现。在您的案例中:

chrome:
    container_name: chrome
    image: selenium/standalone-chrome
    ports:
    - published: 4444
      target: 4444
    environment:
      - JAVA_OPTS=-Dwebdriver.chrome.whitelistedIps=
    networks:
      mynet:
zbq4xfa0

zbq4xfa03#

使用Ruby 3更新解决方案

运行此脚本

docker-compose build
docker-compose up -d chrome
docker-compose run --rm my-integ-tests
docker-compose down

docker-compose.yml

version: '3.9'
services:
  my-integ-tests:
    container_name: my-integ-tests
    image: test/my-integ-tests
    build:
      context: .
      dockerfile: Dockerfile
    environment:
      CHROME_URL: http://chrome:4444/wd/hub
    stdin_open: true
    tty: true
    depends_on:
    - chrome
  chrome:
    container_name: chrome
    image: selenium/standalone-chrome
    environment:
      JAVA_OPTS: -Dwebdriver.chrome.whitelistedIps= -Dwebdriver.chrome.allowedIps=
    shm_size: '2gb'

Dockerfile

#FROM ruby:2.7
FROM ruby:3

RUN apt-get update -y && \
    apt-get -y upgrade && \
    apt-get install -y libarchive-tools zip

RUN gem install bundler

COPY Gemfile Gemfile

RUN bundle install

COPY . .

CMD ["bundle", "exec", "rspec", "/spec/test"]

Gemfile

source "https://rubygems.org"
gem 'rspec'
gem 'capybara'
gem 'capybara-webmock'
gem 'colorize'
gem 'webdrivers'
#gem 'chromedriver-helper'
gem 'selenium-webdriver'
gem 'byebug'
gem 'nokogiri'

spec/spec_helper.rb

require 'colorize'
require 'capybara/dsl'
require 'capybara/rspec'
require 'nokogiri'

RSpec.configure do |config|
  config.color = true
  config.tty = true
  config.formatter = :documentation
  config.include Capybara::DSL
end

def create_web_session
  Capybara.app_host = "https://www.google.com"
  Capybara.run_server = false # don't start Rack

  if ENV['CHROME_URL']
    Capybara.register_driver :remote do |app|
      Capybara::Selenium::Driver.new(app, browser: :remote, options: Selenium::WebDriver::Options.chrome, url: ENV['CHROME_URL'])
    end
    @session = Capybara::Session.new(:remote)
  else
    @session = Capybara::Session.new(:selenium_chrome)
  end
end

def end_web_session(session)
  session.reset!
  session.driver.quit
end

spec/test/demo_spec.rb

require 'spec_helper.rb'
require 'webdrivers/chromedriver'
require 'cgi'

sleep 1

RSpec.describe 'simple tests', type: :feature do

  before(:each) do
    @session = create_web_session
  end

  after(:each) do
    end_web_session(@session)
  end

  it 'Load home page' do
    @session.visit '/'
  end
  
end

相关问题