Отказался подключаться с помощью ChromeDriver, Capybara и Docker Compose

Я пытаюсь перейти с PhantomJS на Chrome без головы и столкнулся с небольшой проблемой. Для локального тестирования я использую Docker Compose, чтобы запустить все зависимые службы. Чтобы подготовить Google Chrome, я использую образ, который объединяет его и ChromeDriver вместе, обслуживая его через порт 4444. Затем я связываю его с контейнером моего приложения следующим образом в этом упрощенном файле docker-compose.yml:

web:
    image: web/chrome-headless
    command: [js-specs]
    stdin_open: true
    tty: true
    environment:
        - RACK_ENV=test
        - RAILS_ENV=test
    links:
        - "chromedriver:chromedriver"

chromedriver:
    image: robcherry/docker-chromedriver:latest
    ports: 
        - "4444"
    cap_add: 
        - SYS_ADMIN
    environment:
        CHROMEDRIVER_WHITELISTED_IPS: ""

Затем у меня есть файл spec/spec_helper.rb, который загружает среду тестирования и связанные с ней инструменты. Я определяю драйвер :headless_chrome и указываю его на локальную привязку ChromeDriver; http://chromedriver:4444. Я почти уверен, что следующее верно:

Capybara.javascript_driver = :headless_chrome

Capybara.register_driver :chrome do |app|
    Capybara::Selenium::Driver.new(app, browser: :chrome)
end

Capybara.register_driver :headless_chrome do |app|
    capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(
    chromeOptions: { args: %w[headless disable-gpu window-size=1440,900] },
)

Capybara::Selenium::Driver.new app,
    browser: :chrome,
    url: "http://chromedriver:4444/",
    desired_capabilities: capabilities
end

Мы также используем видеомагнитофон, но я настроил его так, чтобы он игнорировал любые подключения к порту, используемому ChromeDriver:

VCR.configure do |c|
    c.cassette_library_dir = 'spec/vcr_cassettes'
    c.default_cassette_options = { record: :new_episodes }
    c.ignore_localhost = true
    c.allow_http_connections_when_no_cassette = false
    c.configure_rspec_metadata!
    c.ignore_hosts 'codeclimate.com'
    c.hook_into :webmock, :excon

    c.ignore_request do |request|
        URI(request.uri).port == 4444
    end
end

Я запускаю службы с помощью Docker Compose, который запускает средство запуска тестов. Команда примерно такая:

$ bundle exec rspec --format progress --profile --tag 'broken' --tag 'js' --tag '~quarantined'

Немного подождав, я столкнулся с первым неудачным тестом:

  1) Beta parents code redemption:  redeeming a code on the dashboard when the parent has reached the code redemption limit does not display an error message for cart codes
     Failure/Error: fill_in "code", with: "BOOK-CODE"

     Capybara::ElementNotFound:
       Unable to find field "code"
     # ./spec/features/beta_parents_code_redemption_spec.rb:104:in `block (4 levels) in <top (required)>'

Во всех спецификациях одна и та же ошибка. Итак, я запускаю контейнер, чтобы вручную запускать тесты и захватывать HTML, с которым он тестируется. Я сохраняю его локально и открываю в своем браузере, чтобы увидеть следующую страницу ошибки Chrome. Похоже, что ChromeDriver не оценивает HTML-код спецификации, потому что не может получить к нему доступ, поэтому он пытается запустить тесты на этой странице с ошибкой.

Учитывая приведенную выше информацию, что я здесь делаю неправильно? Я ценю любую помощь, так как отказ от PhantomJS решит очень много головной боли для нас.

Огромное спасибо заранее. Пожалуйста, дайте мне знать, если вам нужна дополнительная информация.

введите описание изображения здесь


person Wilhelm Murdoch    schedule 06.09.2017    source источник
comment
Вы используете RSpec/Capybara на экземпляре докера или на своем локальном компьютере? Если последнее, вам нужно установить Capybara.app_host, чтобы указать на любой адрес вашего локального компьютера из экземпляра докера.   -  person Thomas Walpole    schedule 06.09.2017
comment
@ThomasWalpole Боюсь, в данном случае это первое. Все вещи работают в контейнерах. Спасибо за ответ!   -  person Wilhelm Murdoch    schedule 07.09.2017
comment
Ах, извините - я пропустил веб-контейнер - ответ будет ниже.   -  person Thomas Walpole    schedule 07.09.2017


Ответы (1)


Проблема, с которой вы столкнулись, заключается в том, что Capybara по умолчанию запускает AUT, привязанный к 127.0.0.1, а затем сообщает драйверу, что запрос браузера должен быть оттуда. Однако в вашем случае 127.0.0.1 находится не там, где работает приложение (с точки зрения браузера), поскольку оно находится в другом контейнере, чем браузер. Чтобы это исправить, вам нужно установить Capybara.server_host на любой внешний интерфейс «веб-контейнера» (который доступен из контейнера «chromedriver»). Это приведет к тому, что Capybara привяжет AUT к этому интерфейсу и скажет драйверу, чтобы браузер делал запросы к нему.

В вашем случае это, вероятно, означает, что вы можете указать «веб»

Capybara.server_host = 'web'
person Thomas Walpole    schedule 06.09.2017