Reputation: 38
I'm trying to run rspec tests with Selenium chrome in docker but caught dozens of error. Finally i connected capybara to remote capybara, but now i got these errors:
Got 0 failures and 2 other errors:
1.1) Failure/Error: visit new_user_session_path
Selenium::WebDriver::Error::WebDriverError:
unexpected response, code=404, content-type="text/html"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Action Controller: Exception caught</title>
....................
Failure/Error: raise Error::WebDriverError, msg
Selenium::WebDriver::Error::WebDriverError:
unexpected response, code=404, content-type="text/html"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Action Controller: Exception caught</title>
<style>
body {
background-color: #FAFAFA;
...............
So here is my rails_helper.rb. It's really messy cause I tried dozen times with different configs
require 'simplecov'
SimpleCov.start
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'
require 'turnip/capybara'
require "selenium/webdriver"
require 'capybara-screenshot/rspec'
Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }
Shoulda::Matchers.configure do |config|
config.integrate do |with|
with.test_framework :rspec
with.library :rails
end
end
# 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!
Capybara::Screenshot.register_driver(:headless_chrome) do |driver, path|
driver.browser.manage.window.resize_to(1600, 1200)
driver.browser.save_screenshot("tmp/capybara/chrom_#{Time.now}.png")
end
url = 'http://test.prs.com:3001/'
Capybara.javascript_driver = :remote_browser
Capybara.register_driver :headless_chrome do |app|
capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(
chromeOqptions: { args: %w(headless disable-gpu no-sandbox) }
)
end
capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(
chromeOqptions: { args: %w(headless disable-gpu no-sandbox) }
)
Capybara.default_driver = :remote_browser
Capybara.register_driver :remote_browser do |app|
Capybara::Selenium::Driver.new(app, :browser => :remote, url: url,
desired_capabilities: capabilities)
end
# Capybara::Selenium::Driver.new app,
# browser: :chrome,
# desired_capabilities: capabilities
# end
Capybara.app_host = "http://#{ENV['APP_HOST']}:#{3001}"
Capybara.run_server = false
Capybara.configure do |config|
config.always_include_port = true
end
Chromedriver.set_version '2.32'
# Capybara.javascript_driver = :headless_chrome
# Capybara.server_host= '0.0.0.0'
# Capybara.default_host = "http://test.prs.com"
# Capybara.app_host = "#{Capybara.default_host}:#{Capybara.server_port}"
RSpec.configure do |config|
config.include FactoryGirl::Syntax::Methods
config.include RequestSpecHelper
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
config.fixture_path = "#{::Rails.root}/spec/fixtures"
config.before(:each) do
DatabaseCleaner.strategy = :truncation
DatabaseCleaner.clean
end
config.before(:all, type: :request) do
host! 'test.prs.com'
end
config.use_transactional_fixtures = true
config.infer_spec_type_from_file_location!
config.filter_rails_from_backtrace!
end
And here is my docker-compose.yml:
version: '3'
services:
db:
image: postgres
web:
build: .
command: bundle exec rails s -p 3001 -b '0.0.0.0'
volumes:
- .:/prs
ports: ['3000:3000', '3001:3001']
# - "3001:3001"
depends_on:
- db
- selenium
extra_hosts:
- "test.prs.com:127.0.0.1"
environment:
- APP_HOST=test.prs.com
links:
- selenium
selenium:
image: selenium/standalone-chrome-debug:3.6.0-bromine
# Debug version enables VNC ability
ports: ['4444:4444', '5900:5900']
# Bind selenium port & VNC port
volumes:
- /dev/shm:/dev/shm
shm_size: 1024m
privileged: true
container_name: selenium
I'm new to all this so any help will be appreciated.
Upvotes: 0
Views: 2034
Reputation: 482
My problem was completely unrelated to Docker, Selenium, Capybara, Chromedriver or any of that. They were all red herrings because on my container only tests related to feature specs were failing.
It turns out they were all failing because feature specs are the only part of the app that looks at IP addresses.
I am using the ip_anonymizer
gem and failed to set the IP_HASH_SECRET
for the container. Hopefully, anyone else using this gem with Capybara and CI finds this useful.
Upvotes: 0
Reputation: 49870
From the comments you have clarified that you are trying to run the tests in the web
docker instance while using the selenium driven browser in the selenium docker instance. Additionally, since your tests are working locally I assume you are using Rails 5.1+ so transactional testing for feature tests will work. Based on those parameters there are a few things needed to make everything work properly.
Capybara needs to start its own copy of the app to run the tests against. This is needed for transactional testing to work and for request completion detection. You enable that with
Capybara.run_server = true # You currently have this set to false for some reason
Capybara needs to run its copy of the app on an interface which can be reached from the selenium
docker instance. Easiest way to do that is to specify to bind to 0.0.0.0
Capybara.server_host = `0.0.0.0`
Capybara.server_port = 3001 # I'm assuming this is what you want, change to another port and make sure it's reachable from `selenium` instance if desired
The driver capybara is using needs to be configured to use the selenium instance
Capybara.register_driver :remote_browser do |app|
capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(
chromeOptions: { args: %w(headless disable-gpu no-sandbox) }
)
Capybara::Selenium::Driver.new(app,
:browser => :remote,
url: "http://selenium:4444",
desired_capabilities: capabilities
)
end
Capybara.javascript_driver = :remote_browser
# Capybara.default_driver = :remote_browser # only needed if you want all tests to use selenium rather than just JS tagged tests.
Configure Capybara to use the correct host when visiting relative URLs
Capybara.app_host = "http://web:3001" # a URL that represents the `web` docker instance from the perspective of the `selenium` docker instance
Notes: If you were expecting your tests to run on port 3001 as I guessed, then you want to stop the docker instance from launching rails s
on that port, since you want the tests run against an app instance that Capybara itself launches # command: bundle exec rails s -p 3001 -b '0.0.0.0'
. If the instance you currently have running on 3001 is for something else then you'll need a different port for the tests.
Additionally, if you're not running Rails 5.1+ then you'll need to set config.use_transactional_fixtures = false
and fully configure database_cleaner
- https://github.com/DatabaseCleaner/database_cleaner#rspec-with-capybara-example . If you are using Rails 5.1+ then you can probably remove all the database_cleaner stuff.
Upvotes: 2