How to initialize Selenium driver for altered location of browser - ruby-on-rails

In an attempt to get Minitest to run system tests with a headless browser
class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
driven_by :selenium, using: :headless_firefox
end
the following error is encountered:
Selenium::WebDriver::Error::SessionNotCreatedError: Expected browser binary location, but unable to find binary in default location, no 'moz:firefoxOptions.binary' capability provided, and no binary flag set on the command line
which is expected as the application (on of dozens used) would be drowned in a sea of applications in the OSX default Applications folder.
Now selenium provides the API documentation, but adding after the driven_by line:
options = Selenium::WebDriver::Firefox::Options.new(binary: ['/Users/deploy/_apps/3.\ comms/Firefox.app'])
returns the same error.
How should this directory be set?

Related

Firefox is default but still get WebDriverError: unable to connect to chromedriver 127.0.0.1:9515

I'm setting up Capybara for the first time and it seems to be calling Chrome instead of Firefox by default.
At first I was getting the webdriver error:
Selenium::WebDriver::Error::WebDriverError:
unable to connect to chromedriver 127.0.0.1:9515*
with associated stacktrace
https://pastebin.com/TW5NWJgu
I was able to clear this by adding a gem 'chromedriver-helper' and the test now opens with chromium.
I also tried adding this to both spec_helper and rails_helper:
Capybara.register_driver :selenium do |app|
Capybara::Selenium::Driver.new(app, browser: :firefox)
end
I was able to confirm that rails was able to successfully call firefox because the following command in rails_helper does successfully launch Firefox (but does not take any further action) when I start the test (as per comments, I later removed this command).
RSpec.configure do |config|
driver = Selenium::WebDriver.for :firefox
end
I'm getting the same error on a separate machine and on a different rails app (also didn't have geckodriver set-up on the first pass of Capybara)
My understanding is that Capybara should call Firefox by default. There seems to be a second configuration somewhere that I can't find. Does anyone have an idea of where I might find the line that is calling chrome?
From the log file you provided we can see that you're using Rails 5.1, RSpec 3.8 and Capybara 2.18. Since the log also includes "actionpack-5.1.6/lib/action_dispatch/system_testing/driver.rb" we can tell that you're writing system tests/specs (through rspec-rails). The driver used by system tests is controlled by the driven_by method as documented in the RSpec system spec docs and by default uses the Rails registered :selenium driver which is configured to use Chrome. As documented in the Rails System Test docs you can switch to Firefox by specifying
driven_by :selenium, using: :firefox
Additionally, Capybara 2.18 is pretty much obsolete at this point. You probably want to update to the latest version (3.6 as of now) if you plan on using the latest versions of Firefox/Chrome.

How can I run headless browser system tests in Rails 5.1?

The documentation for Rails 5.1 system tests is a bit sparse. I'm unable to get headless tests that execute javascript running. I think one approach entails installing and running xvf. But this is more manual setup than I'm used to when running capybara in other versions of rails.
What's the most straightforward way to achieve this?
In Rails 5.1 system tests the driver used is set by the driven_by call in ApplicationSystemTestCase (test/application_system_test_case.rb). Assuming you have registered your capybara-webkit driver as 'webkit' you should be able to do
driven_by :webkit
Another potential option if you use Chrome 59+ on linux/mac is to use headless chrome
Capybara.register_driver :headless_chrome do |app|
Capybara::Selenium::Driver.new(app, :browser => :chrome, :args => ['headless'])
end
and then in your test case class
driven_by :headless_chrome
That gives you a headless version of chrome so none of the issues of capybara-webkit/poltergeist not supporting current web standards. Unfortunately currently chromedriver has issues with JS system modals (alert, confirm, prompt - workaround in capybara master branch) and hangs if you attempt to close windows during your tests. Hopefully those 2 issues will be fixed soon.
Also note that rails 5.1 should have removed the need for database_cleaner for most peoples testing since it already handles sharing of a single database connection between multiple threads in test mode.

Rails Capybara selenium test on specific browser version and visualize test

I am currently using Capybara selenium/webkit in functional testing, I don't really understand how it works behind the scene.
By checking the Capybara document, the selenium by default is using firefox browser for testing. It doesn't even mention what is the version it is using. (I didn't install firefox, I think it came together with the gem selenium-webdriver or capybara-webkit)
My question:
1) If I want to trigger my test on specific browser version, is it possible? How can I do that? For example, on Chrome browser version 53.1.2.
2) The automated functional test all conducted behind the scene, is it possible to visualize the testing procedure? For example, Selenium driver launch the browser and visualize the click/scroll/drag effect along with the test running?
The selenium-webdriver gem does not install firefox, and if you're not seeing a browser opening when you run your tests you are not actually using selenium-webdriver, since when used with desktop browsers (firefox, chrome, IE, safari) it will open those browsers and you can watch it interact with the app being tested.
When you run tests Capybara uses the driver identified by Capybara.current_driver at the start of each test. In the normal Capybara configuration (when using rspec) the current driver is set in a before block - https://github.com/teamcapybara/capybara/blob/2.12.0/lib/capybara/rspec.rb#L26 - to either the value of Capybara.javascript_driver or Capybara.default_driver depending on whether the test has a js: true metadata tag or not - see https://github.com/teamcapybara/capybara/blob/2.12.0/README.md#drivers and https://github.com/teamcapybara/capybara/blob/2.12.0/README.md#using-capybara-with-rspec .
By default Capybara.javascript_driver = :selenium and the default config for that driver would use firefox. Therefore if you add the js: true metadata to one of your tests it will use the selenium driver and attempt to run your system installed firefox (depending on versions installed you may also need to install geckodriver), raising errors if there is no FF installed. You will also want to read about database_cleaner in the Capybara README and get that installed correctly for testing. If you don't specify the js: true metadata then (by default) your test is using the rack_test driver which does not process CSS or JS and is really only useful for very basic form and link processing testing. If you want all your tests to run with selenium you could set Capybara.default_driver = :selenium which will then be used for all the tests (you will still need to set up database_cleaner)
The Capybara README has instructions for how to configure the :selenium driver to use Chrome if wanted (you will also need to install chromedriver), and the selenium-webdriver documentation will have details on how you can specify alternate instances of the browsers (if you have multiple versions installed).
If on the other hand you want to use the capybara-webkit gem (or Poltergeist) you would need to specify the name of the registered driver - for instance Capybara.javascript_driver = :webkit/:poltergeist - see their READMEs for details of the different options you can specify for each of those drivers when registering them.

Getting Capybara::DriverNotFoundError when trying to run Cucumber tests

I'm getting this error when I run the cucumber tests. Everything seemed to be working fine the previous day but I can't figure out why it stopped working. I was trying to get capybara webkit working and I had changed a couple of files but I don't see why it should affect my tests. Any idea on how to fix this error I'm getting while running the cucumber tests?
Capybara::DriverNotFoundError: no driver called :rack was found, available drivers: :rack_test, :selenium, :webkit, :webkit_debug
You mentioned that you edited many files. Could it be that you didn't revert all the changes you made? I think Capybara would pick the 'rack_test' driver by default, and your system could not find the 'rack' driver.
Since you're doing Cucumber testing, you must have a file called 'env.rb' under the features/support folder. Make sure you don't force 'rack' as your Capybara driver, and your tests should run fine.

Continuous Integration - Running parallel tests suites that require xvfb

I'm having issues with parallel builds running that require an xvfb server. I was previously using the headless ruby gem, but had sporadic failures when certain test suites that both require capybara-webkit and an xvfb server are running in parallel.
My guess was that they were both trying to use the same DISPLAY, so I attempted to set different DISPLAY values and then run them in parallel, but there was still a failure.
I then tried removing the headless gem and running my test suite with:
DISPLAY=localhost:$display_num.0 xvfb-run bundle exec rake where $display_num is a previously set bash variable that is different between the two test suites.
I then get the error: xvfb-run: error: Xvfb failed to start when they were run in parallel.
Any assistance on deciphering this would be great!
Here is the gist, but ultimately you need to start one headless per process.
This is effectively done with the features/support/javascript.rb file referenced in the gist, the relevant section being:
# Unnecessary on mac
if (!OS.mac? && !$headless_started)
require 'headless'
# allow display autopick (by default)
# allow each headless to destroy_at_exit (by default)
# allow each process to have their own headless by setting reuse: false
headless_server = Headless.new(:reuse => false)
headless_server.start
$headless_started = true
puts "Process[#{Process.pid}] started headless server display: #{headless_server.display}"
end

Resources