I am using Capybara with Selenium driver for my acceptance tests
Versions used:
Selenium 2.53.1
Capybara 2.7.1
cucumber 2.2.0
cucumber-core 1.3.1
According to Selenium/Logging, known log types are browser, client, driver, performance and server. I would like to log all these log types in console output in realtime.
Based on what I understood, to enable full logging I am configuring Capybara as following:
Capybara.configure do |config|
config.run_server = false
config.app_host = ENV['APP_HOST'] # APP HOST from Cucumber.yml file
config.default_driver = :selenium
config.match = :prefer_exact
config.default_max_wait_time = 10
Capybara.register_driver :selenium do |app|
Capybara::Selenium::Driver.new(
app,
:browser => ENV['BROWSER'].downcase.to_sym,
:desired_capabilities => {
:loggingPrefs => {
:browser => "ALL",
:client => "ALL",
:driver => "ALL",
:server => "ALL"
}
}
)
end
end
Where ENV['BROWSER'] is 'Chrome'.
What I am still unclear is how to print the logs to console. I am looking for a way to print the logs for all scenarios.
I tried adding following code to hooks.rb
After do |scenario|
puts #browser.driver.manage.get_log(:browser)
puts #browser.driver.manage.get_log(:client)
puts #browser.driver.manage.get_log(:server)
puts #browser.driver.manage.get_log(:driver)
end
but #browser is nil.
Also tried following in hooks.rb
After do |scenario|
puts page.driver.browser.manage.logs.get(:browser)
end
But works only for browser logs.
Question: How do I print these logs after each scenario, or even better in realtime?
I am trying to set up environment to run my TC in different browsers. But currently TC are run normally just in Chrome browser, Firefox browser is opened but nothing happens (test scenarios are not run) when I am trying to run TC in FF, Opera, Safari browsers.
How to adjust my settings to be able to run TC successfully in all browsers?
Also is there a way to run TC in parallel?
Here is my rails_helper.rb file:
require 'test/unit'
require 'selenium-webdriver'
require 'capybara'
require 'rspec'
require "rails/all"
require 'capybara/rspec'
require "page-object"
require 'rspec/expectations'
require 'securerandom'
require '../Test_helpers/login_helper'
require 'capybara-screenshot/rspec'
require 'launchy'
RSpec.configure do |config|
config.include LoginHelper
config.include RSpec::Matchers
config.include Capybara::DSL
environment = 'firefox'
if environment =='chrome'
Selenium::WebDriver::Chrome.driver_path = '../Resources/chromedriver.exe'
Capybara.default_driver = :chrome
Capybara.register_driver :selenium do |app|
options = {
:js_errors => false,
:timeout => 360,
:debug => false,
:inspector => false,
}
Capybara::Selenium::Driver.new(app, :browser => :chrome)
end
elsif environment =='firefox'
Capybara.default_driver = :firefox
Capybara.register_driver :selenium do |app|
options = {
:js_errors => true,
:timeout => 360,
:debug => false,
:inspector => false,
}
Capybara::Selenium::Driver.new(app, :browser => :firefox)
end
elsif environment == 'safari'
Capybara.default_driver = :safari
Capybara.register_driver :safari do |app|
options = {
:js_errors => false,
:timeout => 360,
:debug => false,
:inspector => false,
}
Capybara::Selenium::Driver.new(app, :browser => :safari)
end
elsif environment == 'opera'
Capybara.default_driver = :opera
Capybara.register_driver :opera do |app|
options = {
:js_errors => false,
:timeout => 360,
:debug => false,
:inspector => false,
}
Capybara::Selenium::Driver.new(app, :browser => :opera)
end
elsif
Capybara.default_driver = :poltergeist
Capybara.register_driver :poltergeist do |app|
options = {
:js_errors => false,
:timeout => 360,
:debug => false,
:phantomjs_options => ['--load-images=no', '--disk-cache=false'],
:inspector => false,
}
Capybara::Poltergeist::Driver.new(app, options)
end
end
Capybara.save_path = "../Reports" # path where screenshots are saved
config.after { |example_group| CapybaraScreenshot.save_and_open_page_path if example_group.exception }
Capybara::Screenshot.register_filename_prefix_formatter(:rspec) do |example|
"screenshot_#{example.description.gsub(' ', '-').gsub(/^.*\/spec\//, '')}"
end
end
Capybara.default_max_wait_time = 15
If you happen to pass here looking for a way to run every test through many browsers, I wrote this (working!) (overly talkative) snippet based on Thomas Walpole's accepted answer:
Rspec.configure do |conf|
Capybara.register_driver :chrome do |mode|
Capybara::Selenium::Driver.new mode, :browser => :remote, :desired_capabilities => :chrome
end
Capybara.register_driver :firefox do |mode|
Capybara::Selenium::Driver.new mode, :browser => :remote, :desired_capabilities => :firefox
end
## Here we politely ask every example to run twice, for each browser we want
conf.around do |example|
puts '~> ' + example.metadata[:example_group][:full_description]
# avoid looping over Capybara.drivers as it will also contain "selenium" generic driver and "rack_test" basic (js-less) browser
[:chrome, :firefox].each do |browser|
Capybara.current_driver = browser
puts "~~> #{example.description} # #{browser}"
example.run
end
end
Capybara.default_driver = :chrome
end
The output ends being something like:
~> The contact page
~~> loads # chrome
~~> loads # firefox
.
Finished in 20.9 seconds (files took 2.69 seconds to load)
1 example, 0 failures
Obviously all puts lines can be removed / commented out, they're there just for sample purposes :)
After each ~~> line the said browser opens and runs the example.
Care must be taken, however, to remove :js => true from your examples, or else Capybara will force-run them against the default javascript_driver instead.
The options you're passing to the drivers you're registering are only valid for poltergeist. Rather than the big if/else you can just register all the drivers and then use the one you need.
RSpec.configure do |config|
config.include LoginHelper # You probably want to only include this for feature tests
config.include RSpec::Matchers # not needed if you use the standard capybara rspec setup by including capybara/rspec
config.include Capybara::DSL # not needed if you use the standard capybara rspec setup by including capybara/rspec
end
Capybara.save_path = "../Reports" # path where screenshots are saved
config.after { |example_group| CapybaraScreenshot.save_and_open_page_path if example_group.exception }
Capybara::Screenshot.register_filename_prefix_formatter(:rspec) do |example|
"screenshot_#{example.description.gsub(' ', '-').gsub(/^.*\/spec\//, '')}"
end
end
Selenium::WebDriver::Chrome.driver_path = '../Resources/chromedriver.exe'
Capybara.register_driver :selenium_chrome do |app|
Capybara::Selenium::Driver.new(app, :browser => :chrome)
end
Capybara.register_driver :selenium_firefox do |app|
Capybara::Selenium::Driver.new(app, :browser => :firefox)
end
Capybara.register_driver :selenium_safari do |app|
Capybara::Selenium::Driver.new(app, :browser => :safari)
end
Capybara.register_driver :selenium_opera do |app|
Capybara::Selenium::Driver.new(app, :browser => :opera)
end
Capybara.register_driver :poltergeist do |app|
options = {
:js_errors => false,
:timeout => 360,
:debug => false,
:phantomjs_options => ['--load-images=no', '--disk-cache=false'],
:inspector => false,
}
Capybara::Poltergeist::Driver.new(app, options)
end
Then set either Capybara.default_driver and/or Capybara.javascript_driver (depending on whether or not you run some tests with rack_test and tag tests that need JS) to the driver you want to use to run your tests.
Capybara.default_driver = :selenium_chrome
To run all your tests against multiple browsers it's normal to configure your CI system to run multiple times and just set a different driver (based on an environment variable for instance) for each run. If you need to run them all in one run you could make your RSpec tests all shared examples and then configure test blocks that include the shared examples but each set a different driver in a before block.
For parallel testing you can look at the parallel_tests gems - https://github.com/grosser/parallel_tests
I used profile["permissions.default.image"] = 2 earlier but now it doesn't work for me:
require "capybara/rspec"
require "selenium/webdriver"
Capybara.register_driver :my_driver do |app|
profile = Selenium::WebDriver::Firefox::Profile.new
profile["permissions.default.image"] = 2
desired_capabilities = Selenium::WebDriver::Remote::Capabilities.firefox firefor_profile: profile
Capybara::Selenium::Driver.new(app,
desired_capabilities: desired_capabilities,
browser: :firefox,
)
end
Capybara.default_driver = :my_driver
feature do
scenario do
visit "http://lenta.ru"
STDIN.gets
end
end
I still see images.
$ /Applications/Firefox.app/Contents/MacOS/firefox-bin -v
Mozilla Firefox 38.3.0
gem "selenium-webdriver", "2.48.0"
I'm working on integrating allure into my tests but have come across a problem with the first test suite failing and returning a undefined method `find_element' for nil:NilClass error with every test in the suite. The tests run as expected when I'm not using allure and the same thing happens regardless of what suite is run.
I've had a look into it and it seems the before and after hooks in my spec helper aren't being used in the failed tests. Any ideas what could be causing this?
require 'rspec'
require 'selenium-webdriver'
require 'allure-rspec'
require 'nokogiri'
require 'uuid'
require 'pathname'
RSpec.configure do |c|
c.include AllureRSpec::Adaptor
c.expect_with :rspec do |c|
### Enable both should and expect syntax ###
c.syntax = [:should, :expect]
end
c.before(:all) do
#Start the Phantom-js driver before running any headless tests
case ENV['browser']
when 'headless'
## Run in command line before a headless test: phantomjs --webdriver=8001
system('start cmd /k phantomjs --webdriver=8001')
sleep 3
end
end
c.before(:each) do
#Find the browser to the used and set the driver to the appropriate one
case ENV['browser']
when 'chrome'
#driver = Selenium::WebDriver.for :chrome
##driver = Selenium::WebDriver.for(:remote, url: 'http://localhost:5555/wd/hub', desired_capabilities: :chrome)
when 'ie'
#driver = Selenium::WebDriver.for :internet_explorer
##driver = Selenium::WebDriver.for(:remote, url: 'http://localhost:5555/wd/hub', desired_capabilities: :ie)
when 'firefox'
#driver = Selenium::WebDriver.for :firefox
##driver = Selenium::WebDriver.for(:remote, url: 'http://localhost:5555/wd/hub', desired_capabilities: :firefox)
when 'headless'
#driver = Selenium::WebDriver.for :remote, url: 'http://localhost:8001'
end
#Maximize the browser
#driver.manage.window.maximize
#driver.get ENV['base_url']
end
c.after(:each) do |c|
#Takes a screen shot if an exception is thrown and attaches it to the allure XML when running Rake tests
if c.exception != nil
$failure = true
c.attach_file("screenshot", File.new(#driver.save_screenshot(File.join(Dir.pwd, "test_reports/allure/#{UUID.new.generate}.png"))))
end
#driver.quit
end
end
AllureRSpec.configure do |c|
#Outputs the Allure XML
c.output_dir = "test_reports/allure"
end
Say I have 3 Scenario Outlines and I need to run scenario 1 with Firefox, close the browser, then run scenario 2 with Chrome, close the browser, then finally run scenario 3 with Firefox.
Is there any way to close/quit the browser in Cucumber/Capybara after each scenario?
So far I have registered two drivers, one for Firefox and one for Chrome:
Capybara.register_driver :selenium_firefox do |app|
Capybara::Driver::Selenium.new(app, :browser => :firefox)
end
Capybara.register_driver :selenium_chrome do |app|
Capybara::Driver::Selenium.new(app, :browser => :chrome)
end
Then in hooks.rb, I'm using a 'custom' tag "#alternate_browser"
Before('#alternate_browser') do
driver = Capybara.current_driver
if driver == :selenium_firefox
Capybara.current_driver = :selenium_chrome
else
Capybara.current_driver = :selenium_firefox
end
end
Is there a way to force the browser to close after each scenario?
EDIT: I tried:
page.evaluate_script("window.close()")
page.execute_script("window.close()")
But both statements had no effect.
This is what you should do.
Stop closing the windows.
Change to explicit browser tags (#firefox,#chrome)
I haven't tried it but this should work.
Capybara.register_driver :selenium_firefox do |app|
Capybara::Driver::Selenium.new(app, :browser => :firefox)
end
Capybara.register_driver :selenium_chrome do |app|
Capybara::Driver::Selenium.new(app, :browser => :chrome)
end
Before('#firefox') do
Capybara.current_driver = :selenium_firefox
end
Before('#chrome') do
Capybara.current_driver = :selenium_chrome
end