简体   繁体   English

Selenium Webdriver不适用于docker-compose

[英]Selenium webdriver not working with docker-compose

I have a docker-compose.yml as given below with service defined for selenium using selenium/standalone-chrome-debug image. 我有一个docker-compose.yml,如下所示,其中使用selenium/standalone-chrome-debug映像为硒定义了服务。

# docker-compose.yml

version: '3'

services:
  webapp:
    tty: true
    stdin_open: true
    container_name: webapp
    depends_on:
      - postgres
      - elasticsearch
      - redis
      - selenium
    build: .
    volumes:
      - .:/webapp
    ports:
      - "3000:3000"
    entrypoint: sh /webapp/setup.sh
    environment:
      - REDISTOGO_URL=redis://redis:6379
      - ELASTICSEARCH_URL=http://elasticsearch:9200
      - SELENIUM_HOST=selenium
      - SELENIUM_PORT=4444

  postgres:
    container_name: postgres
    image: postgres:9.5.17
    ports:
      - "5432:5432"
    volumes:
      - ./postgres:/var/lib/postgresql
    environment:
      - POSTGRES_PASSWORD=test
      - POSTGRES_USER=test
      - POSTGRES_DB=test

  redis:
    container_name: redis
    image: redis:5.0.5-alpine
    command: redis-server
    hostname: redis
    ports:
      - "6379:6379"
    volumes:
      - redis:/data

  sidekiq:
    build: .
    command: bundle exec sidekiq
    volumes:
      - .:/webapp
    depends_on:
      - postgres
      - redis
    environment:
      - REDISTOGO_URL=redis://redis:6379

  elasticsearch:
    image: elasticsearch:6.8.0
    container_name: elasticsearch
    ports:
      - "9200:9200"
    depends_on:
      - postgres
    volumes:
      - esdata:/usr/share/elasticsearch/data

  selenium:
    image: selenium/standalone-chrome-debug
    ports:
      - "4444:4444"

volumes:
  redis:
  postgres:
  esdata:

And rails_helper.rb 和rails_helper.rb

# rails_helper.rb

require 'database_cleaner'
require 'simplecov'
SimpleCov.start('rails') do
  coverage_dir 'coverage'
  add_group 'Modules', 'app/modules'
  add_filter "lib/api_constraints.rb"
  add_filter "app/uploaders/"
  add_filter "app/models/redactor_rails/"
  add_filter "app/controllers/application_controller.rb"
  add_filter "app/models/application_record.rb"
  add_filter "app/workers/"
end

# This file is copied to spec/ when you run 'rails generate rspec:install'
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
# Prevent database truncation if the environment is production
abort("The Rails environment is running in production mode!") if Rails.env.production?
require 'spec_helper'
require 'rspec/rails'
Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
# Add additional requires below this line. Rails is not loaded until this point!

require 'capybara/rspec'
require 'net_http_ssl_fix'
require 'selenium-webdriver'
require 'webdrivers/chromedriver'
require 'spree/testing_support/capybara_ext'
require 'rack_session_access/capybara'
require 'capybara-screenshot/rspec'
require 'rspec/retry'

# Add rake task example group
require 'support/tasks'

# Force lock local timezone for test environment
ENV['TZ'] = 'UTC'

Webdrivers.cache_time = 86_400
selenium_host = "http://127.0.0.1:4444/wd/hub"

unless ENV['SELENIUM_HOST'].nil?
  selenium_host = "http://#{ ENV["SELENIUM_HOST"] }:4444/wd/hub"
end

Capybara.register_driver :selenium_chrome do |app|
  caps = Selenium::WebDriver::Remote::Capabilities.chrome(
    browserName: 'chrome',
    "chromeOptions" => {
      args: ['headless','no-sandbox','disable-gpu','window-size=1920x1080']
    }
  )
  Capybara::Selenium::Driver.new(
    app,
    browser: :chrome,
    url: selenium_host,
    desired_capabilities: caps
  )
end

Capybara.server = :puma, { Silent: true }
Capybara.javascript_driver = :selenium_chrome
Capybara.save_path = "#{ Rails.root }/tmp/screenshots/"

Capybara.raise_server_errors = false
Capybara.default_max_wait_time = 10
Capybara.asset_host = 'http://localhost:3000'
Capybara.configure do |config|
  config.match = :prefer_exact
  config.ignore_hidden_elements = false
  config.visible_text_only = true
  # accept clicking of associated label for checkboxes/radio buttons (css psuedo elements)
  config.automatic_label_click = true
end
Capybara.always_include_port = true

# Requires supporting ruby files with custom matchers and macros, etc, in
# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
# run as spec files by default. This means that files in spec/support that end
# in _spec.rb will both be required and run as specs, causing the specs to be
# run twice. It is recommended that you do not name files matching this glob to
# end with _spec.rb. You can configure this pattern with the --pattern
# option on the command line or in ~/.rspec, .rspec or `.rspec-local`.
#
# 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 }

# Checks for pending migration and applies them before tests are run.
# If you are not using ActiveRecord, you can remove this line.
ActiveRecord::Migration.maintain_test_schema!

RSpec.configure do |config|

  config.expect_with :rspec do |c|
    # enable both should and expect
    c.syntax = [:should, :expect]
  end
  # If you're not using ActiveRecord, or you'd prefer not to run each of your
  # examples within a transaction, remove the following line or assign false
  # instead of true.
  config.use_transactional_fixtures = true

  config.append_after(:each) do
    Capybara.reset_sessions!
  end

  config.include Capybara::DSL

  config.order = "random"
  config.use_transactional_fixtures = false

  config.before(:suite) do
    DatabaseCleaner.clean_with(:truncation)
    # compile front end
    WebpackerHelper.compile_once
    # disable searchkick callbacks, now enabled by using search hook
    Searchkick.disable_callbacks
  end

  # hook for enabling searchkick callbacks
  config.around(:each, search: true) do |example|
    Searchkick.callbacks(true) do
      example.run
    end
  end

  config.before(:each) do
    DatabaseCleaner.strategy = Capybara.current_driver == :rack_test ? :transaction : :truncation
    DatabaseCleaner.clean
    DatabaseCleaner.start
    DownloadHelper.clear_downloads
    Factory.seed_data
  end

  config.after(:each) do
    Capybara.app_host = nil # don't change me, explicitly set host in each spec appropriately
    DatabaseCleaner.clean
    Timecop.return
  end

  config.include DeviseHelpers
  config.include Devise::Test::ControllerHelpers, type: :controller
  config.include CommonHelper
  config.include ImageHelper
  config.include CommonSpecHelper
  config.include ReactComponentHelper
  config.include BraintreeHelper
  config.include BookingSpecHelper
  config.include CapybaraRspecExt
  config.include DownloadHelper
  config.include ActionView::Helpers::NumberHelper
  config.include ActionView::Helpers::DateHelper

  config.infer_spec_type_from_file_location!

  # Filter lines from Rails gems in backtraces.
  config.filter_rails_from_backtrace!
  # arbitrary gems may also be filtered via:
  # config.filter_gems_from_backtrace("gem name")

  # Suppress Braintree noise
  null_logger = Logger.new("/dev/null")
  null_logger.level = Logger::INFO
  Braintree::Configuration.logger = null_logger

  config.after(:example, :on_fail => :screenshot) do |example|
    full_screenshot if example.exception
  end
  config.after(:example, :on_fail => :open_page) do |example|
    save_and_open_page if example.exception
  end

  # set parallel env for searchkick
  Searchkick.index_suffix = ENV['TEST_ENV_NUMBER']

  # show retry status in spec process
  config.verbose_retry = true
  # default number of retries
  config.default_retry_count = 0
  # sleep for 1 seconds before retry
  config.default_sleep_interval = 1
  # Retry failing specs (conditions to retry are set in config.retry_count_condition)
  config.around :each do |ex|
      ex.run_with_retry
  end
  # Retry failing JS specs or failing specs with specific exception
  config.retry_count_condition = proc do |ex|
    if (ex.metadata[:js] || [Net::ReadTimeout].include?(ex.exception.class)) && !ex.metadata[:on_fail]
      nil # will fallback to config.default_retry_count
    else
      0 # no retries if conditions not matched
    end
  end
  # callback to be run between retries
  config.retry_callback = proc do |ex|
    Capybara.reset!
  end
end

When I run docker-compose exec webapp rspec spec/feature/test_spec.rb for feature spec with js: true it fails with following stacktrace: 当我使用js:true运行docker-compose exec webapp rspec spec / feature / test_spec.rb以获取功能说明时,true失败并显示以下stacktrace:

  Failure/Error: ex.run_with_retry

          Selenium::WebDriver::Error::WebDriverError:
            <unknown>: Failed to read the 'sessionStorage' property from 'Window': Access is denied for this document.
              (Session info: chrome=75.0.3770.100)

 # #0 0x5651e686d7a9 <unknown>
          # /usr/local/bundle/gems/selenium-webdriver-3.142.3/lib/selenium/webdriver/remote/response.rb:72:in `assert_ok'
          # /usr/local/bundle/gems/selenium-webdriver-3.142.3/lib/selenium/webdriver/remote/response.rb:34:in `initialize'
          # /usr/local/bundle/gems/selenium-webdriver-3.142.3/lib/selenium/webdriver/remote/http/common.rb:88:in `new'
          # /usr/local/bundle/gems/selenium-webdriver-3.142.3/lib/selenium/webdriver/remote/http/common.rb:88:in `create_response'
          # /usr/local/bundle/gems/selenium-webdriver-3.142.3/lib/selenium/webdriver/remote/http/default.rb:114:in `request'
          # /usr/local/bundle/gems/selenium-webdriver-3.142.3/lib/selenium/webdriver/remote/http/common.rb:64:in `call'
          # /usr/local/bundle/gems/selenium-webdriver-3.142.3/lib/selenium/webdriver/remote/bridge.rb:167:in `execute'
          # /usr/local/bundle/gems/selenium-webdriver-3.142.3/lib/selenium/webdriver/remote/w3c/bridge.rb:567:in `execute'
          # /usr/local/bundle/gems/selenium-webdriver-3.142.3/lib/selenium/webdriver/remote/w3c/bridge.rb:305:in `execute_script'
          # /usr/local/bundle/gems/selenium-webdriver-3.142.3/lib/selenium/webdriver/remote/w3c/bridge.rb:277:in `clear_session_storage'
          # /usr/local/bundle/gems/selenium-webdriver-3.142.3/lib/selenium/webdriver/common/html5/session_storage.rb:40:in `clear'
          # /usr/local/bundle/gems/capybara-3.20.0/lib/capybara/selenium/driver.rb:325:in `clear_session_storage'
          # /usr/local/bundle/gems/capybara-3.20.0/lib/capybara/selenium/driver.rb:317:in `clear_storage'
          # /usr/local/bundle/gems/capybara-3.20.0/lib/capybara/selenium/driver_specializations/chrome_driver.rb:45:in `clear_storage'
          # /usr/local/bundle/gems/capybara-3.20.0/lib/capybara/selenium/driver.rb:291:in `clear_browser_state'
          # /usr/local/bundle/gems/capybara-3.20.0/lib/capybara/selenium/driver.rb:446:in `reset_browser_state'
          # /usr/local/bundle/gems/capybara-3.20.0/lib/capybara/selenium/driver.rb:125:in `reset!'
          # /usr/local/bundle/gems/capybara-3.20.0/lib/capybara/selenium/driver_specializations/chrome_driver.rb:36:in `reset!'
          # /usr/local/bundle/gems/capybara-3.20.0/lib/capybara/session.rb:128:in `reset!'
          # /usr/local/bundle/gems/capybara-3.20.0/lib/capybara.rb:315:in `block in reset_sessions!'
          # /usr/local/bundle/gems/capybara-3.20.0/lib/capybara.rb:315:in `reverse_each'
          # /usr/local/bundle/gems/capybara-3.20.0/lib/capybara.rb:315:in `reset_sessions!'
          # /usr/local/bundle/gems/capybara-3.20.0/lib/capybara/rspec.rb:18:in `block (2 levels) in <top (required)>'
          # /usr/local/bundle/gems/rspec-retry-0.6.1/lib/rspec/retry.rb:123:in `block in run'
          # /usr/local/bundle/gems/rspec-retry-0.6.1/lib/rspec/retry.rb:110:in `loop'
          # /usr/local/bundle/gems/rspec-retry-0.6.1/lib/rspec/retry.rb:110:in `run'
          # /usr/local/bundle/gems/rspec-retry-0.6.1/lib/rspec_ext/rspec_ext.rb:12:in `run_with_retry'
          # ./spec/rails_helper.rb:224:in `block (2 levels) in <top (required)>'
          # /usr/local/bundle/gems/rspec-retry-0.6.1/lib/rspec/retry.rb:123:in `block in run'
          # /usr/local/bundle/gems/rspec-retry-0.6.1/lib/rspec/retry.rb:110:in `loop'
          # /usr/local/bundle/gems/rspec-retry-0.6.1/lib/rspec/retry.rb:110:in `run'
          # /usr/local/bundle/gems/rspec-retry-0.6.1/lib/rspec_ext/rspec_ext.rb:12:in `run_with_retry'
          # /usr/local/bundle/gems/rspec-retry-0.6.1/lib/rspec/retry.rb:37:in `block (2 levels) in setup'

Is there anything that I am missing? 有什么我想念的吗? What is the correct way to setup selenium with docker-compose? 用docker-compose设置硒的正确方法是什么?

Since you're using the selenium standalone server setup you need to configure the Capybara selenium driver for remote usage. 由于您使用的是硒独立服务器设置,因此需要配置Capybara硒驱动程序以供远程使用。

Capybara.register_driver :selenium_chrome do |app|
  options = Selenium::WebDriver::Chrome::Options.new(args: %w[
    headless no-sandbox disable-gpu window-size=1920x1080
  ])
  Capybara::Selenium::Driver.new(
    app,
    browser: :remote,
    desired_capabilities: :chrome,
    options: options
    url: selenium_host,
  )
end

Other notes: 其他说明:

  • If you're using Rails 5.1+ you can probably remove all the database cleaner stuff and just enable transactional tests 如果您使用的是Rails 5.1+,则可能会删除所有数据库清理程序,而仅启用事务测试

  • Setting ignore_hidden_elements = false is a terrible idea when writing tests since you generally only want to be dealing with elements the user can actually see 在编写测试时,将ignore_hidden_elements = false设置为一个糟糕的主意,因为您通常只想处理用户实际上可以看到的元素

  • :smart is generally a better default for Capybara.match (rather than :prefer_exact) if you care about making sure your tests are referring to the elements you expect them to be. 如果您想确保测试引用的是您期望的元素,那么:smart通常是Capybara.match的更好默认设置(而不是:prefer_exact)。

  • You shouldn't be including Capybara::DSL in every RSpec test type 您不应该在每种RSpec测试类型中都包含Capybara :: DSL

You need the hub image which is missing in the above compose file. 您需要上述撰写文件中缺少的集线器映像。 Link the hub image to node image 将集线器映像链接到节点映像

selenium-hub:
 image: selenium/hub:3.14.0
 container_name: hub
 ports:
 - "4444:4444"
node-chrome:
 image: selenium/node-chrome-debug:3.14.0
 links:
 - selenium-hub

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM