Selenium IDE export working strangely with Test::Unit and Ruby - ruby

I'm new to Selenium and I think I got Selenium IDE to work quite nicely, but something strange is happening (perhaps a bug) when I export Selenium IDE (2.5.0) Test Case to a Ruby Test::Unit / WebDriver test. My test works fine when I run it from Selenium IDE, but after I exported it to Ruby the following code doesn't work:
verify { assert_match /.*Welcome/, #driver.find_element(:xpath, "//title").text }
On Selenium IDE the same test is defined as:
Command: verifyText
Target: //title
Value: regexp:.*Welcome
and it works fine (attached screenshot)
Below is the Test::Unit error message for: verify { assert_match /.*Welcome/, #driver.find_element(:xpath, "//title").text } So there is some kind of problem with the RegEx I guess. The title should end with the word 'Welcome'.
jyrki#ubu:~/rails_projects/p3$ rake test test/selenium/employer_signup_ruby2_test.rb
Loaded suite /home/jyrki/.rvm/gems/ruby-2.1.0/bin/rake
Started
F
===============================================================================
Failure:
test_employer_signup_ruby2(EmployerSignupRuby2)
/home/jyrki/rails_projects/p3/test/selenium/employer_signup_ruby2_test.rb:17:in `teardown'
<[]> expected but was
<[#<Test::Unit::AssertionFailedError: <""> expected to be =~
</.*Welcome/>.>]>
diff:
+ [#<Test::Unit::AssertionFailedError: <""> expected to be =~
? [ ]
? </.*Welcome/>.>
===============================================================================
Finished in 12.747676835 seconds.
1 tests, 2 assertions, 1 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications
100% passed
0.08 tests/s, 0.16 assertions/s
Run options: --seed 25544
# Running tests:
Finished tests in 0.003802s, 0.0000 tests/s, 0.0000 assertions/s.
0 tests, 0 assertions, 0 failures, 0 errors, 0 skips
Below is the code that works apart from the one line of the code:
require "json"
require "selenium-webdriver"
gem "test-unit" #?
require "test/unit"
class EmployerSignupRuby2 < Test::Unit::TestCase
def setup
#driver = Selenium::WebDriver.for :firefox
#base_url = "http://0.0.0.0:3000/"
#accept_next_alert = true
#driver.manage.timeouts.implicit_wait = 30
#verification_errors = []
end
def teardown
#driver.quit
assert_equal [], #verification_errors
end
def test_employer_signup_ruby2
#driver.get(#base_url + "/employer_signup")
#driver.find_element(:id, "employer_first_name").clear
#driver.find_element(:id, "employer_first_name").send_keys "tester"
#driver.find_element(:id, "employer_last_name").clear
#driver.find_element(:id, "employer_last_name").send_keys "login-tester"
#driver.find_element(:id, "employer_email").clear
#driver.find_element(:id, "employer_email").send_keys "tester012345678901#test.com"
#driver.find_element(:id, "employer_password").clear
#driver.find_element(:id, "employer_password").send_keys "foobar"
#driver.find_element(:id, "employer_password_confirmation").clear
#driver.find_element(:id, "employer_password_confirmation").send_keys "foobar"
#driver.find_element(:name, "commit").click
verify { assert_match /.*Welcome/, #driver.find_element(:xpath, "//title").text }
end
def element_present?(how, what)
#driver.find_element(how, what)
#${receiver}.find_element(how, what)
true
rescue Selenium::WebDriver::Error::NoSuchElementError
false
end
def alert_present?()
#driver.find_element(how, what)
#${receiver}.switch_to.alert
true
rescue Selenium::WebDriver::Error::NoAlertPresentError
false
end
def verify(&blk)
yield
rescue Test::Unit::AssertionFailedError => ex
#verification_errors << ex
end
def close_alert_and_get_its_text(how, what)
alert = #driver.switch_to().alert()
#alert = ${receiver}.switch_to().alert()
alert_text = alert.text
if (#accept_next_alert) then
alert.accept()
else
alert.dismiss()
end
alert_text
ensure
#accept_next_alert = true
end
end
Actually, I can get the test to work (sort of) when I replace the one line of code with this:
verify { assert #driver.find_element(:xpath, '//title[contains(.,"Welcome")]') } #works!!
However if the “Welcome” text is missing (=test is failing), then the fix will remain in a loop indefinitely and I have interrupt (Ctrl + C) the test. So far this is the best fix I have found. If you know a better fix, please let me know, thanks :-)
My Gemfile has the following rails/selenium/test versions:
gem 'rails', '4.0.2'
gem 'selenium-webdriver', '~> 2.41.0' #this is the latest version
gem 'test-unit', '2.5.5'
gem 'rake', '10.2.2'
--
$ bundle show json
The gem json has been deleted. It was installed at:
/home/jyrki/.rvm/rubies/ruby-2.1.0/lib/ruby/gems/2.1.0/gems/json-1.8.1
Ruby 2.1.0
In addition, the export creates ruby code: ${receiver}.find_element(how, what) that doesn't work; so I needed to change it to #driver.find_element(how, what) to make it work.
Also, export creates a gem statement in addition to require statement for test-unit (lines 3-4):
gem "test-unit" #?
require "test/unit"
I might ask about this issue from Selenium Users Google Group as well
Btw, do you know if Selenium IDE exports work better with RSpec than Test::Unit?

Related

I want to call def setup method before all tests in minitest ruby

This is my code
class TestLogin < MiniTest::Test
def setup
#driver=Selenium::WebDriver.for :firefox
#driver.manage.window.maximize
#driver.navigate.to "http://google.com"
end
def test_case1
puts "testcase1"
end
def test_case2
puts "testcase2"
end
end
I want to run setup method only once for two testcases at the starting.
You can use minitest-hooks gem with before_all something like:
require "minitest/autorun"
require 'minitest/hooks/test'
class TestLogin < MiniTest::Test
include Minitest::Hooks
def before_all
puts "setup .."
end
def test_case1
puts "testcase1"
end
def test_case2
puts "testcase2"
end
end
Now when you run the test you should see something like:
Run options: --seed 58346
# Running:
setup ..
testcase1
.testcase2
.
Finished in 0.001259s, 1588.7504 runs/s, 0.0000 assertions/s.
2 runs, 0 assertions, 0 failures, 0 errors, 0 skips

Selenium Does Click on Firefox but PhantomJS doesn't (Ruby)

i'm really new to Selenium WebDriver. I write a simple code for out of curiousity. I made an spam bot to open a page, shuffle in online users list and click everyone of them in order. Send some message, close the new window and repeat.
I made this work on Selenium Firefox driver. It seems work good. But i want to do it silent, not opening firefox everytime. So i found out i can do that by PhantomJS.
Here is my working code for firefox:
require 'selenium-webdriver'
def setup
#driver = Selenium::WebDriver.for :firefox
#reklam = 'Some testing message.'
end
def run
setup
#driver.get 'http://c2.me/okanb3'
first_window = #driver.window_handle
begin
#driver.switch_to.window(first_window)
#driver.find_element(link_text: "Shuffle").click
sleep 20
elements = #driver.find_elements(:class, 'shufflelink')
elements.each do |x|
x.click
all_windows = #driver.window_handles
new_window = all_windows.select { |this_window| this_window != first_window }
#driver.switch_to.window(new_window)
if #driver.page_source.include? 'The user is not available right now.' or #driver.page_source.include? 'User account is disabled.'
#driver.close
#driver.switch_to.window(first_window)
else
input = #driver.find_element(:id, 'inputbox')
input.send_keys(#reklam)
input.send_keys:return
#driver.close
popup = #driver.switch_to.alert
popup.accept
#driver.switch_to.window(first_window)
end
end
end while TRUE
end
run
But when i switch Webdriver from Firefox to PhantomJS, x.click method doesn't work. I made some tests and program doesnt go further from click method. After a while program ends with (Net::ReadTimeout) error.
Here is my last try to work it proper;
require 'selenium-webdriver'
def setup
#driver = Selenium::WebDriver.for :phantomjs
#reklam = 'http://peyloride.com siteme beklerim.'
end
def teardown
#driver.quit
end
def run
setup
#driver.manage.window.resize_to(1920, 1080)
#driver.get 'http://c2.me/okanb3'
first_window = #driver.window_handle
begin
#driver.switch_to.window(first_window)
#driver.find_element(link_text: "Shuffle").click
puts "Shuffleandı"
sleep 20
elements = #driver.find_elements(:class, 'shufflelink')
elements.each do |x|
puts "click'e geldik"
#driver.save_screenshot "phantomjs.png"
x.click
#driver.save_screenshot "phantomjs2.png"
puts "click yaptı sonunda aq"
all_windows = #driver.window_handles
new_window = all_windows.select { |this_window| this_window != first_window }
#driver.switch_to.window(new_window)
if #driver.page_source.include? 'The user is not available right now.' or #driver.page_source.include? 'User account is disabled.'
#driver.close
#driver.switch_to.window(first_window)
else
input = #driver.find_element(:id, 'inputbox')
input.send_keys(#reklam)
input.send_keys:return
#driver.close
popup = #driver.switch_to.alert
popup.accept
#driver.switch_to.window(first_window)
end
end
end while TRUE
end
run
As you can see i tried to take a screenshot to understand the problem but screenshot seems really fine. Here it is:
EDIT: Versions:
ruby -v
ruby 2.2.3p173 (2015-08-18 revision 51636) [x86_64-linux]
gem list
...
selenium-webdriver (2.48.1)
...
phantomjs -v
1.9.0

RSpec: Always execute before(:all) in begin/rescue

I'm writing Selenium tests, using Watir-Webdriver and RSpec, which can be a bit spotty when they're first being developed. I've run into a situation where I want to create something on the UI in before :all, however it can throw exceptions (based on timing or poor loading). When that happens I want to take a screenshot.
Here's what I have:
RSpec.configure do |config|
config.before(:all) do |group| #ExampleGroup
#browser = Watir::Browser.new $BROWSER
begin
yield #Fails on yield, there is no block
rescue StandardError => e
Utilities.create_screenshot(#browser)
raise(e)
end
end
end
I run it and get an error:
LocalJumpError: no block given (yield)
The reason I assumed yielding would work is RSpec's definition of before:
def before(*args, &block)
hooks.register :append, :before, *args, &block
end
How can I wrap the code I've put in my before :all in a begin/rescue block without having to do it on every suite?
Thanks in advanced.
The code you've written in the before hook is the &block you're referring to in RSpec::Hooks#before. The hook yields to your code, then runs your tests after the yield is complete.
As for how to make this work, I think this should do:
RSpec.configure do |config|
# ensures tests are run in order
config.order = 'defined'
# initiates Watir::Browser before all tests
config.before(:all) do
#browser = Watir::Browser.new $BROWSER
end
# executes Utilities.create_screenshot if an exception is raised by RSpec
# and the test is tagged with the :first metadata
config.around(:each) do |example|
example.run
Utilities.create_screenshot(#browser) if example.exception && example.metadata[:first]
end
end
This configuration requires the first test be tagged with metadata:
describe Thing, :first do
it "does something" do
# ...
end
end
This way, you'll only take a screenshot at the beginning of your run for a failing test, and not after every failing test. If you'd rather not mess with metadata (or prefer your tests are run in random order), you could do something like this:
RSpec.configure do |config|
# initiates Watir::Browser before all tests
config.before(:all) do
#test_count = 0
#browser = Watir::Browser.new $BROWSER
end
# executes Utilities.create_screenshot if an exception is raised by RSpec
# and the test is the first to run
config.around(:each) do |example|
#test_count += 1
example.run
Utilities.create_screenshot(#browser) if example.exception && #test_count == 1
end
end
This works for me. Instead of begin/rescue in the before :all hook,
config.after :each do
example_exceptions = []
RSpec.world.example_groups.each do |example_group|
example_group.examples.each do |example|
example_exceptions << !example.exception.nil?
end
end
has_exceptions = example_exceptions.any? {|exception| exception}
#Handle if anything has exceptions
end

Selenium WebDriver for ruby fails with "too many redirects"

I've got this simple test case that tests a login form.
For some reason webdriver refuses to run the test and comes back with a "too many redirects" message. The page is just an ordinary login screen, very simple and there are no redirects whatsoever. Access from the server to the page seems ok.
I'm using selenium-webdriver-2.25.0 on a centos server.
Below the error message:
(...)
[WARNING] MultiJson is using the default adapter (ok_json). We recommend loading a different JSON library to improve performance.
EE
Finished in 0.206445 seconds.
1) Error: test_login(Login):
Selenium::WebDriver::Error::WebDriverError: too many redirects
/usr/lib/ruby/gems/1.8/gems/selenium-webdriver-2.25.0/lib/selenium/webdriver/remote/http/default.rb:62:in `request'
/usr/lib/ruby/gems/1.8/gems/selenium-webdriver-2.25.0/lib/selenium/webdriver/remote/http/default.rb:63:in `request'
/usr/lib/ruby/gems/1.8/gems/selenium-webdriver-2.25.0/lib/selenium/webdriver/remote/http/common.rb:40:in `call'
(...)
My code:
require "rubygems"
require "selenium-webdriver"
require "test/unit"
class Login < Test::Unit::TestCase
def setup
#driver =Selenium::WebDriver.for(:remote, :url => "http://selenium.server.com/wd/hub")
#base_url = "http://www.myservice.com"
#driver.manage.timeouts.implicit_wait = 30
#verification_errors = []
end
def teardown
#driver.quit
assert_equal [], #verification_errors
end
def test_login
#driver.get(#base_url + "/login/")
#driver.find_element(:id, "username").clear
#driver.find_element(:id, "username").send_keys "user#server"
#driver.find_element(:id, "password").clear
#driver.find_element(:id, "password").send_keys "mykeys!"
#driver.find_element(:xpath, "//input[#value='Login']").click
verify { assert element_present?(:link, "Logout") }
verify { assert element_present?(:link, "Settings") }
verify { assert element_present?(:link, "Products") }
end
def element_present?(how, what)
#driver.find_element(how, what)
true
rescue Selenium::WebDriver::Error::NoSuchElementError
false
end
def verify(&blk)
yield
rescue Test::Unit::AssertionFailedError => ex
#verificatiohttp://jenkins.dev.emesa-auctions.com/cms/n_errors << ex
end
end
UPDATE
It seems that no matter what url I use for the 'base url' the errors keeps occuring.
I managed to solve this problem myself. The issue was that I was accessing the server through its public facing url (selenium.server.com) instead of through the internal lan url (which bypass the firewall).
Changing that fixed the problem.

Model not being saved using Selenium but saved using Rack::Test

I have the following test that works in Rack::Test but not using Selenium. I.e. if I add , js: true to the describe block, I get an error message in Firefox saying that it couldn't find the License with id=(the id of #l)
describe "should hide allocation rule # for pdf & clickthrough licenses" do
it "reads current state and shows/hides fields appropriately" do
#l = FactoryGirl.create(:license:,
way: License::CLICK_WAY)
visit edit_admin_license_path(#l)
end
end
Why? I must be missing something. I can verify with Sequel Pro that the record is not getting saved when using js: true.
I need this spec to run in Selenium because I have javascript to test.
The simple solution was to turn transactional fixtures off.
Why does my Cucumber test fail when run with Selenium?
in spec/spec_helper.rb:
RSpec.configure do |config|
config.use_transactional_fixtures = false
config.before :each do
if Capybara.current_driver == :rack_test
DatabaseCleaner.strategy = :transaction
else
DatabaseCleaner.strategy = :truncation
end
DatabaseCleaner.start
end
config.after do
DatabaseCleaner.clean
end
end
and in the Gemfile, test section
gem 'database_cleaner'

Resources