Multiple concurrent browser tests with watir-webdriver through different browsers - ruby

so I'm working on a website here and I would like to run multiple browser tests at one time. What I mean by this is it should perform my smoke tests on ie, firefox and chrome at the same time and report back each browser results. I'm currently only testing with ie with rpsec and watir-webdriver but would like to automate for the other 2 browsers. Are there any existing gems out there (I haven't been able to find any), if not what would be the best way to go around solving this issue?

You should try WatirGrid.
It won't make all the work for you but it will give you a platform to launch multiple tests at once. The you can just launch the same test 3 times changing the target browser and the grid will handle where they will be executed.

Why don't need anything except watir-webdriver to run multiple browsers on the same machine.
ie = Watir::Browser.new :ie
firefox = Watir::Browser.new :firefox
chrome = Watir::Browser.new :chrome
opera = Watir::Browser.new :opera

If you have multiple machines or VMs to work with, Jenkins in the answer. My approach is similar to Chuck's, but instead of a flat configuration file I let Jenkins prompt for these values via drop-down menu, etc. Jenkins is easy to set up and can automatically distribute test jobs to any available machine for testing.
So, I click "Google Search Test" and select "Internet Explorer"... then I do the same thing and select a different browser. Concurrent tests in various browsers, with HTML/email output and a great log history.
I'll also be writing more about this, but I'm still on vacation!
Here is an example of configuration file (these assign default values if for example Jenkins is not used to launch them). NOTE: "||=" means "if nil, use this value. If not nil, use the current value". I'm only setting values if Jenkins has not already.
ENV['BROWSER'] ||= "firefox"
ENV['ENVIRONMENT'] ||= "qa"
ENV['LIMIT'] ||= "10"
ENV['DISTRICT'] ||= "any"
ENV['TYPE'] ||= "pkg-new"
# Not necessary, but added for sanity/cleanliness:
$type = ENV['TYPE'].downcase
$browser = ENV['BROWSER'].downcase
$env = ENV['ENVIRONMENT'].downcase
$district = ENV['DISTRICT'].downcase
puts "\t** Testing #{$env.upcase} using #{$browser.upcase}... **"
The Jenkins portion is surprisingly easy - so easy I didn't think it was set up. You create a Variable for your script, and whatever you name the variable becomes ENV["VariableName"] - and is immediately available to your script.
So I have a variable named "BROWSER" that is set by a drop down with Firefox, IE and Chrome options. The user has no room to confuse the script with free text, and they can run a custom test whenever they want. My Devs/PMs/Users love me :D.

If you want to run the exact same test code for the tests you will need to externalize the browser type, either as an environment variable, or a YAML file or somesuch.
Ruby has some stuff that makes dealing with yaml files super easy (I need to write a blog posting on this) so you can put something at the top of your script that calls a method to get the config info and then set the browser type accordingly.
In my testconfig.yml YAML file I have:
global:
browser: ie #possible values: ie, ff, chrome
note I don't currently test against opera (market segment too small) or it would be in the list of possible values. The comment is just there to make life easy on whoever might have to edit that file.
I have a read_config method defined in a readconfig.rb file which looks (in part) like this
require 'yaml'
def read_config
config = YAML.load_file('testconfig.yml')
$browser_type = config['global']['browser']
end
And at the top of my tests there is code like this
require 'rubygems'
require 'readconfig'
require 'watir-webdriver'
read_config
$browser = Watir::Browser.new $browser_type.to_sym
This way I can have a different config file on each system (which also sets up a lot of other things like the current passwords (changed on a regular basis), which test environment to use, and settings for each environment for stuff like the test server URL's, database server and name, etc. When developing tests a simple change to the config file lets me run all the tests facing a given browser. or if I want to run in parallel I can have the systems setup with their own customized config file, let them pull the current scripts from source control, and then run them against whatever browser, server etc is configured in the config file.
This is probably dirt simple stuff to any accomplished ruby dev, but it's like magic for any of us new to ruby, and especially for getting hard-coded values OUT of my scripts and into one single place where I can control and change them.

Related

Annoying Guard notification when testing

Recently I made a simple ruby application and have been using minitest to test it.
Following the advice of the Head First Ruby book, I automated this testing using Rake(I'll write what it told me to put in the Rakefile at the end of this post, in case that helps). The test seems to run fine (everything passes in a way I would expect it to), but I always get this notification at the end of it all:
rvm/gems/ruby-2.3.0/gems/guard-2.14.0/lib/guard/notifier.rb:28: warning: instance variable #notifier not initialized
Testing things manually by telling ruby to include which files I want, does not have this issue, only when I use "rake test" to test things.
As far as I can tell, this is related to when I set up Guard when I was following Michael Hartl's Rails Tutorial, at the end of chapter 3. I followed the directions for setting that up (correctly, as far as I can tell), and this was all in a completely different folder(ultimately my ruby and rails projects do have the same parent folder that they sit in, but are themselves in completely separate ruby_projects and rails_projects folders). If possible, I would like to stop this notification on my ruby application that I am testing. Is there a good way to do this?
Contents of the Rakefile I am using, if that helps:
require "rake/testtask"
Rake::TestTask.new(:test) do |t|
t.libs << "lib"
t.test_files=FileList['test/**/test_*.rb']
end
My test file requires minitest/autorun, and the file for the application that I am testing, then has the normal tests
Seems like there's some weird conflict...
The reason is that Guard::Notifier.connect isn't connected. Normally, when you run guard, Guard.setup is called which does this.
If you're not using guard (e.g. interactively), then calling the following from your Rakefile should work around the problem:
Guard::Notifier.connect(notify: false, silent: true)
Guard::Notifier.disconnect
This will initialize the variable.
For a faster response, always report such issues on the project page on Github. If you can share the project where this occurs, maybe a better fix is possible. (It's best to provide a repository, since it really speeds up fixing things and often errors like this are very hard to simulate without the exact code).

Difference between scraping and testing mode in CasperJS

I'm absolutely new to CasperJS and I'm wondering what's the difference between those 'two modes'.
Both access the DOM, it seems that test mode has a limited access and functionality.
I looked for this question around and didn't find the answer.
In test mode you have access to the tester module and with it access to asserts, test suites and (xml) reports. This is not accessible in plain mode anymore (earlier versions than 1.1-beta4 had access to some of the test mode stuff in plain mode).
The only drawback to test mode is that you can only have one casper instance which is injected. This leads to:
When you try to create it, you will get an error.
(Nearly) all options have to be assigned directly and cannot be passed to create as an object.
Some things cannot be done like this one: A: How to open a new tab in CasperJS

why send_keys can't work after right click in chrome and ie, but firefox is fine?

i want to copy a image in the page with right click and alt+y,and follow code is work well in the firefox,but chrome and ie. so i can't get the image from the clipboard.
require 'watir-webdriver'
b = Watir::Browser.new :chrome
b.goto('www.baidu.com')
b.img(:src=>"http://www.baidu.com/img/baidu_sylogo1.gif").right_click
b.send_keys ("{alt}y")
and follow code can work well
require 'watir-webdriver'
b = Watir::Browser.new :chrome
b.goto('www.baidu.com')
b.send_keys :tab
this can work well
When you do b.send_keys ("{alt}y"), you are just typing the letters {, a, l, etc.
Try this instead:
b.send_keys([:alt, 'y'])
Watir and Watir-Webdriver use different inputs for send_keys - see here.
Note: I did not test your full script with this. To be honest, I cannot figure out how to manually copy the image to clipboard using alt+y.
It would help to know why you want to save the image. Would a screen shot work? If it will, try this:
b.driver.save_screenshot "#{Time.now.to_i}.png"
Based on one of the previous comments, its sounds like you ultimately just need a way to save the image. I assume copying it to clipboard is not actually important.
So you do all your navigation in Watir-Webdriver and then switch to one of the other Ruby gems (ex Open-URI or Net-Http) to download the image.
The following is an example using Open-URI:
require 'watir-webdriver'
require "open-uri"
save_file = 'C:\Documents and Settings\Setup\Desktop\image.png'
b = Watir::Browser.new :chrome
b.goto('www.baidu.com')
image_location = b.img.src
File.open(save_file, 'wb') do |fo|
fo.write open(image_location).read
end
Do not waste any time trying to automate validation such as a Captcha (Completely Automated Public Turing Test To Tell Computers and Humans Apart) or other authentication system designed to thwart automation. Yes it can be done but it is effectively engaging in an arms race or tilting at windmills. More importantly it brings no value to your employer.
The right way to automate around a captcha or verification code is to configure the test environment such that the code is predictable. Many captcha tools, or verification tools, have the ability to operate in 'test' mode where they have a set response. You'd never configure a production environment that way, but you can easily (and ought to) configure a test environment that way.
Talk to the folks who setup and control the test environment. They just need some logic that knows it's a test env and then uses the proper api call for the captcha or authorization tool (like the google authorizer, or the widgets that spit out numbers every 5 minutes) to put it in test mode so it uses a predictable validation response.
Here is an example of what I am talking about: http://captcha.biz/doc/aspnet/api/captcha-configuration-reference.html#BotDetect.Configuration.ITestModeConfiguration
If you are using something that does not support this, then you can either configure the system to skip the captcha entirely, OR you can configure it to point some test stub that you create (instead of the real captcha system). This will be a small bit of code that you or your developers create that uses the same api as a real captcha, but always expects the same answer. In that case everything behaves exactly like it was talking to a real captcha service, but the little stub code it is talking to always sends the same image with the same 'answer' e.g. 'testing'
This sort of thing is normal for test environments, where all sorts of third party stuff is either disabled, or put into a test mode, or connected to a test sandbox (e.g. captcha's, advertising, website analytics, tracking pixels, credit card authorization services, etc)

Running rspec against multiple targets

I've written an rspec test using Watir against a web application and it's running fine. However, I now want to be able to run this test against the web application running on different domain names.
My initial thought was that I'd be able to pass a value to spec at the command line to set a variable within my script, but I can't see any easy method of doing this. So my second thought was that I might need to add an array of domains into my script and have it test all of them - but I don't always want to test every domain, and the domains are constantly changing as we add and remove sites to be tested.
What are my options for allowing the choice of targets I want?
You can set an environment variable, as those get passed on. RSpec uses this for its rake tasks, btw.
In your spec you can do something like:
before { #host = ENV['TARGET'] || 'default_target.com' }
You can run it like this:
TARGET=google.com spec .
Or:
TARGET=stackoverflow.com rake spec

Run script directly in 2 various browsers

I have created Ruby test script that use Selenium RC to test my web app directly in 2 browsers(IE, Firefox). My script runs - first on IE then continue on Firefox and then should be continued and finished in already opened IE browser. My problem is: I can't continue(reconnect) to run my script in already opened IE browser. I use:
#browser = RSpecSeleniumHelper.connect_browser("URL")
but it opens with new session (it needs to keep previous session).
Is there a particular reason you need to switch between browsers half way through?
I have no idea how you'd fix the problem, but it seems like it would be best solved by running the tests in one browser at a time.
I'm also unsure why you need to switch back and forth in your browsers.
Regardless, I'm doing something similar, but instead I use a different library. I'm using the "Selenium" gem. (gem install selenium) and here's what I would do in your situation.
#ie_driver = Selenium::SeleniumDriver.new(rc_host, port, "*iexplore", url, 1000)
#ie_driver.start
#ie_driver.whatever //Test code
#ff_driver = Selenium::SeleniumDriver.new(rc_host, port, "*firefox", url, 1000)
#ff_driver.start
#ff_driver.whatever //Test code
#ff_driver.stop
#ie_driver.whatever //Continue test code with IE
#ie_driver.stop
In summary, while I'm not really familiar with your selenium library, typically I would create 2 instances of the R/C driver, that way I won't have to interrupt the session.

Resources