从容器化 RSpec/Capybara 和 Selenium Chrome 访问文件下载

Accessing file downloads from containerized RSpec/Capybara and Selenium Chrome

我想在 Docker 中 运行 一个 RSpec/Capybara 测试套件。此测试套件执行文件下载。

如果我 运行 带有 rspec 的测试套件,我可以访问下载的文件。

如果我 运行 同时 rspec 和 selenium chrome 作为容器,我不知道如何访问下载的文件。

.ruby-版本

2.7.0

宝石文件

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

spec/spec_helper.rb

require 'colorize'
require 'capybara/dsl'
require 'capybara/rspec'
require 'byebug'

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://github.com'
  Capybara.run_server = false # don't start Rack

  if ENV['CHROME_URL']
    Capybara.register_driver :selenium_chrome_headless do |app|
      args = [
        '--no-default-browser-check',
        '--start-maximized',
        '--headless',
        '--disable-dev-shm-usage',
        '--whitelisted-ips'
      ]
      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
  end
  @session = Capybara::Session.new(:selenium_chrome_headless)
  #@session = Capybara::Session.new(:selenium_chrome)
end

spec/test/demo_spec.rb

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

sleep 1

RSpec.describe 'basic_tests', type: :feature do
  before(:each) do
    @session = create_web_session
  end

  it 'Load page' do
    @session.visit '/docker/compose/releases/tag/1.27.0'
    @session.find_link('Source code (zip)')
    @session.click_link('Source code (zip)')
    sleep 3
    f = File.join('compose-1.27.0.zip')
    expect(File.exists?(f)).to be true
    File.delete(f)
  end

end

Docker文件

FROM ruby:2.7

RUN gem install bundler

COPY Gemfile Gemfile
COPY Gemfile.lock Gemfile.lock

RUN bundle install

COPY . .

RUN chmod 777 .

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

docker-compose.yml

version: '3.7'
networks:
  mynet:
services:
  rspec-chrome:
    container_name: rspec-chrome
    image: rspec-chrome
    build:
      context: .
      dockerfile: Dockerfile
    environment:
      CHROME_URL: http://chrome:4444/wd/hub
    stdin_open: true
    tty: true
    networks:
      mynet:
    depends_on:
    - chrome
  chrome:
    container_name: chrome
    image: selenium/standalone-chrome
    networks:
      mynet:
    volumes:
    - /dev/shm:/dev/shm

运行宁rspec

时的输出
basic_tests
  Load page

Finished in 8.45 seconds (files took 6.79 seconds to load)
1 example, 0 failures

当运行宁docker-compose up -d --build

时输出

docker logs -f rspec-chrome

basic_tests
  Load page (FAILED - 1)

Failures:

  1) basic_tests Load page
     Failure/Error: expect(File.exists?(f)).to be true
     
       expected true
            got false
     # /spec/test/demo_spec.rb:17:in `block (2 levels) in <top (required)>'

当您有 Chrome 个下载文件时,它们将被下载到 Chrome 容器中,因此要从容器中访问它们 运行 您可能需要创建共享卷的测试在两个容器之间并将其挂载为 Chromes 下载目录。

以下修改解决了我的问题。

spec/spec_helper.rb

在chrome选项

中传递以下首选项
        "prefs" => {
          'download.default_directory' => '/tmp',
          'download.directory_upgrade' => true,
          'download.prompt_for_download' => false
        }

这是完整的文件

require 'colorize'
require 'capybara/dsl'
require 'capybara/rspec'
require 'byebug'

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://github.com'
  Capybara.run_server = false # don't start Rack

  if ENV['CHROME_URL']
    Capybara.register_driver :selenium_chrome_headless do |app|
      args = [
        '--no-default-browser-check',
        '--start-maximized',
        '--headless',
        '--disable-dev-shm-usage',
        '--whitelisted-ips'
      ]
      caps = Selenium::WebDriver::Remote::Capabilities.chrome("chromeOptions" => {
        "args" => args,
        "prefs" => {
          'download.default_directory' => '/tmp',
          'download.directory_upgrade' => true,
          'download.prompt_for_download' => false
        }
      })

      Capybara::Selenium::Driver.new(
        app,
        browser: :remote,
        desired_capabilities: caps,
        url: ENV['CHROME_URL']
      )
    end
  end
  @session = Capybara::Session.new(:selenium_chrome_headless)
  #@session = Capybara::Session.new(:selenium_chrome)
end

spec/test/demo_spec.rb

将目录更改为 /tmp 并在 /tmp 中查找下载

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

sleep 1

RSpec.describe 'basic_tests', type: :feature do
  before(:each) do
    @session = create_web_session
    Dir.chdir "/tmp"
  end

  it 'Load page' do
    @session.visit '/docker/compose/releases/tag/1.27.0'
    @session.find_link('Source code (zip)')
    @session.click_link('Source code (zip)')
    sleep 3
    f = File.join('/tmp','compose-1.27.0.zip')
    expect(File.exists?(f)).to be true
    File.delete(f)
  end

end

docker-compose.yml

在 rspec 和 chrome 容器之间将 /tmp 作为 docker 卷共享

version: '3.7'
networks:
  mynet:
volumes:
  downloads:
services:
  rspec-chrome:
    container_name: rspec-chrome
    image: rspec-chrome
    build:
      context: .
      dockerfile: Dockerfile
    environment:
      CHROME_URL: http://chrome:4444/wd/hub
    stdin_open: true
    tty: true
    networks:
      mynet:
    depends_on:
    - chrome
    volumes:
    - downloads:/tmp
  chrome:
    container_name: chrome
    image: selenium/standalone-chrome
    networks:
      mynet:
    volumes:
    - /dev/shm:/dev/shm
    - downloads:/tmp