I Trying to open multiple instance of Firefox browser from my ruby code.
I use selenium 2.53.4 and firefox 47.0.2
The problem is after the thread has been created, the driver not initiate imidiately. it's took so long time until it's opened. And the second driver will opened after the first one is almost finished, this make multithread useless.
Here is my code
require "selenium-webdriver"
th = Array.new
i = 0
limit = 3
while i < 10
if(Thread.list.count <= 3)
th[i] = Thread.new(i){ |index|
start = Time.new
puts "#{index} - Start Initiate at #{start}"
driver = Selenium::WebDriver.for :firefox
finish = Time.new
puts "#{index} - Finish Initiate at #{finish}"
driver.get "http://google.com"
sleep(10)
driver.quit
puts "#{index} - Finished"
}
i = i + 1
puts "Thread - #{i} Created"
end # end if
end # end while
th.each{|t|
if(!t.nil?)
t.join
end
}
Did I code it properly? or it's firefox limitation? or selenium?
Note :
When I remove the thread it's take lesser time (about 6 s until navigate to intended URL)
it's work great using chrome driver
Related
# load in the webdriver gem to interect with selenium
require 'selenium-webdriver'
#setup chrome plugin
driver = Selenium::WebDriver::Chrome.driver_path='C:\Users\vidhi\Desktop\Ruby Folder\chromedriver.exe'
#this line will start the browser
driver = Selenium::WebDriver.for :chrome
wait = Selenium::WebDriver::Wait.new(:timeout => 20)
def document_initialised(driver)
driver.execute_script('return initialised')
end
#Navigate to URl
driver.get "http://automationpractice.com/index.php?controller=authentication&back=my-account#account-creation"
#Maximize the window
driver.manage.window.maximize
sleep 6
driver.action.key_down(:enter).perform
sleep 5
driver.find_element(:id,"email_create").send_keys "demouser099#gmail.com"
sleep 5
driver.action.key_down(:enter).perform
driver.find_element(:id,"SubmitCreate").click
sleep 2
driver.action.key_down(:enter).perform
#### Check that the radio button exists
puts "Test Passed: Radio button found" if wait.until {
driver.find_element(:id,"uniform-id_gender2").displayed?
}
#Change the state of the Radio Buttons
cb1 = wait.until {
element1 = driver.find_element(:id,"uniform-id_gender1")
element1 if element1.displayed?
}
cb1.click if cb1.selected? == false
cb3 = wait.until {
element2 = driver.find_element(:id,"uniform-id_gender2")
element2 if element2.displayed?
}
cb3.click if cb3.selected? == false
sleep 4
driver.find_element(:id,"customer_firstname").send_keys "demo"
sleep 3
driver.find_element(:id,"customer_lastname").send_keys "user"
sleep 5
password=driver.find_element(:id,"passwd").send_keys "demo#123"
sleep 4
if driver.find_element(:id,"uniform-days").displayed?
puts "Days dropdown is displayed.."
select = driver.find_element(:id,"uniform-days")
alloptions = select.find_elements(:tag_name,"option")
puts alloptions.size
alloptions.each do |option|
puts "Value is.."+option.attribute("value")
if option.attribute("value")=="20"
option.click
puts "Value has been selected.."
sleep 5
break
end
end
end
month_dropdown = driver.find_element(:id,"months")
months=Selenium::WebDriver::Support::Select.new(month_dropdown)
months.select_by(:text,"April ")
puts driver.find_element(:id,"months").text.include?("April")
years_dropdown = driver.find_element(:id,"years")
years=Selenium::WebDriver::Support::Select.new(years_dropdown)
years.select_by(:index,28)
sleep 3
driver.find_element(:id,"address1").send_keys "45 calony A"
sleep 4
if driver.find_element(:id,"uniform-id_state").displayed?
puts "State dropdown is displayed.."
select = driver.find_element(:id,"uniform-id_state")
alloptions = select.find_elements(:tag_name,"option")
puts alloptions.size
alloptions.each do |option|
puts "Text is.."+option.attribute("text")
if option.attribute("text")=="California"
option.click
puts "text has been selected.."
sleep 5
break
end
end
end
#Enter city
driver.find_element(:id,"city").send_keys "Los Angeles"
sleep 4
driver.find_element(:id,"postcode").send_keys "23654"
Country_dropdown =driver.find_element(:id,"id_country")
country=Selenium::WebDriver::Support::Select.new(Country_dropdown)
country.select_by(:index,1)
sleep 5
#Input Mobile Number
driver.find_element(:id,"phone_mobile").send_keys "985256238"
sleep 5
#Click on Submit button
driver.find_element(:id,"submitAccount").click
sleep 5
I have write script for registration form I have run my automation script then on first time it is successfully pass but when run twice with same email id then it is showing validation message as email already exists try with new one..so for this validation what is the assertion in ruby?
Here is the link for registration form-http://automationpractice.com/index.php?controller=authentication&back=my-account#account-creation
General side notes:
I see that you have a method defined that you don't use.
def document_initialised(driver)
driver.execute_script('return initialised')
end
Also there seems to be some un-nneeded variable assignment and not-needed driver.action.key_down(:enter).perform
It is possible to create a class to keep your code more structured ;)
To your question:
I would create an if to check if the error is displayed on the page or not after you did you submit with driver.find_element(:id,"SubmitCreate").click. You can see an example in about it in #register_email in my example.
If I create some class from it and do some other removal of code I think is obsolete, it looks like this (but it has not been tested by me).
# load in the webdriver gem to interect with selenium
require 'selenium-webdriver'
class RegisterUser
def run
return unless register_email
do_the_rest
end
private
def driver
return #driver if #driver.present?
Selenium::WebDriver::Chrome.driver_path='C:\Users\vidhi\Desktop\Ruby Folder\chromedriver.exe'
#driver = Selenium::WebDriver.for(:chrome)
#driver.get "http://automationpractice.com/index.php?controller=authentication&back=my-account#account-creation"
sleep 6
#driver.manage.window.maximize
#driver
end
def wait
Selenium::WebDriver::Wait.new(:timeout => 20)
end
def register_email
driver.find_element(:id,"email_create").send_keys "demouser099#gmail.com"
driver.find_element(:id,"SubmitCreate").click
sleep 5
return true unless driver.find_element(:id,"create_account_error").displayed?
# An account using this email address has already been registered.
# Please enter a valid password or request a new one.
puts driver.find_element(:id,"create_account_error").text
false
end
def do_the_rest
# Here you can put the rest of the code, or clean up even more and split into multiple methods
end
end
RegisterUser.new.run
I am making an automation program using Watir , that reads links from a file links.txt and then open one by one on chrome browser. When it takes to much time to open then browser and its on loading time it shows me the Net::ReadTimeout. I have tried to rescue and and if its not rescued go to the next link from the list.
I have tried this one but when max_retries = 3 it shows again the error. I want to make browser to wait for specific amount of time and then if it is still loading close the browser and go to the next link from the list
file='links.txt'
max_retries = 3
times_retried = 0
n = 0
begin
browser = Watir::Browser.new :chrome
Watir.default_timeout = 1000
rescue Net::ReadTimeout
browser.wait
retry
end
line = File.readlines(file).sample
while n <= 50 do
n+=1
begin
browser.goto "#{line}"
rescue Net::ReadTimeout => error
if times_retried < max_retries
times_retried += 1
puts "Failed to load page, retry #{times_retried}/#{max_retries}"
retry
else
puts "Exiting script. Timeout Loading Page"
exit(1)
end
end
break if n == 50
end
You have to increase the page load time out, it waits default time of 60 seconds but you can increase the page load timeout by the following code
client = Selenium::WebDriver::Remote::Http::Default.new
client.read_timeout = 120 # seconds
driver = Selenium::WebDriver.for :chrome,http_client: client
b=Watir::Browser.new driver
Now your code would wait for 120 seconds for any page load which has been caused by #click and also wait to load the url by goto method.
This is an old question, but maybe that helps someone:
client = Selenium::WebDriver::Remote::Http::Default.new
client.timeout = 600 # instead of the default 60 (seconds)
Watir::Browser.new :chrome, http_client: client
No matter what I try to do, the browser tries to run the test too fast before it has a chance to find the element that I am looking for. If I put in a simple "sleep 2", it has a chance for the drop down menu to drop and load and successfully find the element. But I am wanting to learn to use the Selenium Wait command. I have tried numerous combinations of the below and looked all over the web for documentation or perhaps examples. I have found plenty of firefox and people say that some of the things below worked perfectly in firefox, but for me and my project team mates, we can not get any of the waits, implicit or explicit, to pause long enough for it to detect the element. The element does not exist until the drop down menu is fully dropped, then it can detect it. It doesn't take 2 seconds but it seems that none of my wait commands will actually make it wait. Like I said, I have tried numerous different things and almost all of them are below. If anyone can help guide me, i would appreciate it. Here is some of the code I have tried:
def setup
#driver = Selenium::WebDriver.for :chrome
#driver.get "https://website.herokuapp.com/"
#wait = Selenium::WebDriver::Wait.new(:timeout => 10) # seconds
# #driver = Selenium::WebDriver.for:chrome
# #driver.manage.timeouts.implicit_wait = 30
# #wait = Selenium::WebDriver::Wait.new(:timeout => 15)
# #wait = Selenium::WebDriver::Wait.new(:timeout => 10)
# #driver.manage.timeouts.implicit_wait = 10
# #wait = Selenium::WebDriver::Wait.new(timeout: 10)
#driver.manage.window.maximize()
# #driver.navigate.to("https://website.herokuapp.com/")
end
def test_user_name_is_present
login()
#driver.find_element(:class, "navbar-toggle").click()
# user = #driver.find_element(:class, "dropdown-toggle").text
# #wait.until{#driver.find_element(:class, "dropdown-toggle")}
#driver.find_element(:class, "dropdown-toggle")
#wait.until { #driver.find_element(:class => "dropdown-toggle") }
user = #driver.find_element(:class, "dropdown-toggle").text
assert_equal(true, user.include?('HEATHER'), "no user")
end
I'm more familiar with JavaScript or Java bindings.
But what about:
def test_user_name_is_present
login()
#driver.find_element(:class, "navbar-toggle").click()
#wait.until { #driver.find_element(:class => "dropdown-toggle").displayed? }
user = #driver.find_element(:class, "dropdown-toggle").text
assert_equal(true, user.include?('HEATHER'), "no user")
end
Our team uses this, just add to your test_helper.rb if using rails
def wait_for_ajax(sleep_sec = 4)
assert page.has_no_content?(:css, 'body.loading')
sleep sleep_sec if sleep_sec
end
I was trying to make a script that downloads all images or videos from a thread in my favourite imageboard: 2ch.hk
I was successful until I wanted to download these files asynchronously (for example, to improve performance)
Here is the code http://ideone.com/k2l4Hm
file = http.get(source).body
require 'net/http'
multithreading = false
Net::HTTP.start("2ch.hk", :use_ssl => true) do |http|
thread = http.get("/b/res/133467978.html").body
sources = []
thread.scan(/<a class="desktop" target="_blank" href=".+">.+<\/a>/).each do |a|
source = "/b#{/<a class="desktop" target="_blank" href="\.\.(.+)">.+<\/a>/.match(a).to_a[1]}"
sources << source
end
i = 0
start = Time.now
if multithreading
threads = []
sources.each do |source|
threads << Thread.new(i) do |j|
file = http.get(source).body #breaks everything
# type = /.+\.(.+)/.match(source)[1]
# open("#{j}.#{type}","wb") { |new_file|
# new_file.write(file)
# }
end
i += 1
end
threads.each do |thr|
thr.join
end
# until downloade=sources.size
#
# end
else
sources.each do |source|
file = http.get(source).body
type = /.+\.(.+)/.match(source)[1]
open("#{i}.#{type}","wb") { |new_file|
new_file.write(file)
}
i += 1
print "#{(((i).to_f / sources.size) * 100).round(2)}% "
end
puts
end
puts "Done. #{i} files were downloaded. It took #{Time.now - start} seconds"
end
I suppose that this line crashes everything.
file = http.get(source).body
Or maybe that's the problem.
threads.each do |thr|
thr.join
end
Error messages are always different, from Bad File Descriptor and IO errors to "You may have encountered a bug in the Ruby interpreter or extension libraries."
If you want to try and run my code, please substitute a link to thread in 4th line with a new thread (from 2ch.hk/b), because the one in my code may be deleted by the time you run my code
Version of ruby: 2.3.1, OS Xubuntu 16.10
You'll probably have much better performance using a ruby http lib that supports parallel requests:
https://github.com/typhoeus/typhoeus
e.g.
hydra = Typhoeus::Hydra.new
10.times.map{ hydra.queue(Typhoeus::Request.new("www.example.com", followlocation: true)) }
hydra.run
The problem with my code is that I can't make multiple requests on a Net::HTTP instance at the same time.
The solution is to open an HTTP connection for each thread.
I'm communicating with an RS232 keypad that has an LCD. On each keypress I write the key that was pressed to the LCD to provide feedback to the user.
If no key is pressed within 10 seconds I'd like to abandon waiting for input.
I've written some code that will timeout if the user isn't done entering a multi-character value within 10 seconds, what I'd rather do is give the user another 10 seconds to complete input after each keypress.
Is this possible using timeout.rb?
require 'rubygems'
require 'serialport'
require 'timeout'
sp = SerialPort.new('/dev/tty.usbserial', 9600, 8, 1, SerialPort::NONE)
sp.write("Input:")
begin
timeout(10) do
input = ""
sp.each_byte do |byte|
#call to increase timeout.rb timer would go here
input << byte.chr
sp.write("Input:" + input)
end
end
rescue Timeout::Error
puts "Timed out!"
exit
end
puts input
I found an alternative way of achieving the desired effect by using Threads instead of timeout.rb but would be interested to learn alternative methods.
require 'rubygems'
require 'serialport'
sp = SerialPort.new('/dev/tty.usbserial', 9600, 8, 1, SerialPort::NONE)
sp.write("Input:")
input = ""
timer = Time.now + 10
t = Thread.new do
sp.each_byte do |byte|
timer = Time.now + 10
input << byte.chr
sp.write("Input:" + input)
end
end
t.kill unless Time.now < timer while t.alive?