Unable to use OptionParser and rspec - ruby

I have a simple watir (web-driver) script which goes to google. But, I want to use option parser to set an argument in the cmd to select a browser. Below is my script:
require 'optparse'
require 'commandline/optionparser'
include CommandLine
require 'watir-webdriver'
describe 'Test google website' do
before :all do
options = {}
opts = OptionParser.new do |opts|
opts.on("--browser N",
"Browser to execute test scripts") do |n|
options[:browser] = n
$b = n.to_s
end
end
opts.parse! ARGV
p options
end
describe 'The test website should be displayed' do
it 'should go to google' do
$ie = Watir::Browser.new($b)
#go to test website
$ie.goto("www.google.com")
end
end
end
Executing rspec ietest.rb --browser firefox -f doc
just gives me invalid option, ietest is the name of my file. Any other intuitive ways of setting a browser through web driver, with out changing script code, would be welcome.

You cannot use rspec with OptionParser since the rspec executable itself parses its own options. You cannot "piggy back" your options on the rspec options.
If you must do something like this then use either a settings file (spec_config.yml or similar), or use an environment variable:
BROWSER=firefox spec test_something.rb
And then in your code you can use ENV['BROWSER'] to retrieve the setting.

Please, learn about RSpec because I am guessing you have no clue about it (just google it). There are no expectations and you are writing your functionality in it.
require 'optparse'
require 'commandline/optionparser'
include CommandLine
require 'watir-webdriver'
options = {}
opts = OptionParser.new do |opts|
opts.on("--browser N",
"Browser to execute test scripts") do |n|
options[:browser] = n
end
opts.parse! ARGV
p options
ie = Watir::Browser.new(options[:browser].to_s)
#go to test website
ie.goto("www.google.com")
That should work.
EDIT: If you want to test it do something like this:
def open_url_with_browser(url, browser = 'firefox')
nav = Watir::Browser.new(browser)
nav.goto(url)
end
Then you would test that method in a spec. Just stub new, and goto in different specs.
If you are still wondering why are you getting the invalid option is because you are passing --browser to rspec, not your script, as intended.

Related

Use a command line option to call a method

So I guess this is kind of related to my last question, but I was wondering if there was a way to call a method by using a command line option. Say you had a method like this:
def b
puts "Hello brian"
end
is there a way to write something like this:
ruby mine.rb -b
and get this
Hello brian
I already tried looking for this online and discovered OptionParser but I have yet to discover anything involving the OptionParser calling a method previously created.
There are a lot of ways to do this, depending on the use case. The below code is taken from the Ruby docs with the extra method added.
Realistically you'd probably want a class that handles the different options and encapsulates the method instead of having them at the file scope.
#!/usr/bin/env ruby
require 'optparse'
options = {}
OptionParser.new do |opts|
opts.banner = "Usage: example.rb [options]"
opts.on("-b", "Run method 'b'") do |v|
options[:b] = true
end
end.parse!
def b
puts "Hello Brian"
end
if options[:b]
b
end
I've also added a shebang at the top that will automatically call ruby. As long as your script file is executable you can call it directly (ie. ./mine.rb -b).

Undefined method 'should' when using .text.include? with watir and ruby

I am trying to verify text on a web page.
The line of code using is: #browser.test.include?('Favorites').should==true
When the script executes this line I get the error: undefined method 'should' for false:FalseClass (NoMethodError)
Here is the full code:
require 'watir-webdriver'
require 'rspec'
#browser=Watir::Browser.new :ff
#browser.goto('http://enoteca.demo.episerver.com/en-US/')
#browser.link(:text=>'Register').wait_until_present
#browser.text.include?("Favorites").should==true
You need to define an example group that contains one or more examples. For instance:
require 'watir-webdriver'
require 'rspec'
describe "an example group" do
it "is an example" do
browser = Watir::Browser.new
browser.goto('www.example.org')
browser.text.include?('Domain').should==true
end
end
If you place the above in a file ending with _spec.rb (e.g. foo_spec.rb), you can run it at command line or terminal: rspec foo_spec.rb. After completion, rspec will return a status:
Finished in X.XX seconds (files took X.XXXX seconds to load)
1 example, 0 failures
Also, the should method has been deprecated in rspec3 (although it will still work for now). In fact, rspec3 will return a deprecation warning if you use should.
Using should from rspec-expectations' old :should syntax without explicitly
enabling the syntax is deprecated. Use the new :expect syntax or explicitly enable :should with config.expect_with(:rspec) { |c| c.syntax = :should } instead.
Here's the same spec as above but using expect instead of should:
describe "an example group" do
it "is an example" do
browser = Watir::Browser.new
browser.goto('www.example.org')
expect(browser.text).to include 'Domain' # expect method instead of should
end
end
While I would think you should be using an example group (as #orde mentioned), it is not technically required. You can use the expectations outside an example group by including the RSpec::Expectations:
require 'watir-webdriver'
require 'rspec'
# Include the expectations so that they do not need an example group
include RSpec::Expectations
#browser=Watir::Browser.new :ff
#browser.goto('http://enoteca.demo.episerver.com/en-US/')
#browser.link(:text=>'Register').wait_until_present
#browser.text.include?("Favorites").should==true

Running minitest handler tests inside another ruby script

I'd like to run my minitest handler tests inside another ruby script (a bootstrapper script of sorts). I'd like to return the results of my tests to a variable that I can then parse to make sure everything passed before moving on. Is this possible? If so, what does the syntax for something like this look like?
You can shell out to run the test and capture the output.
puts "Running foo test:"
output = `ruby -Ilib:test test/test_foo.rb`
puts output
puts "Completed foo test."
Okay so I figured out how to do this using the rake::test library. This code will execute a minitest test, then slurp in the xml from the report and determine if everything passed or not.
require 'rake'
require 'rake/testtask'
require 'ci/reporter/rake/minitest'
require 'xmlsimple'
Rake::TestTask.new do |t|
t.verbose = true
t.test_files = FileList['system_tests/vm_tests.rb']
end
task :test => :"ci:setup:minitest"
Rake::Task[:test].execute
results = XmlSimple.xml_in('test/reports/TEST-VMtests.xml')
if results["failures"] > 0 or results["errors"] > 0
raise "The VM Tests have resulted in failures or errors"
end

Parallel Cucumber/Watir scenarios in *Windows*

Any thoughts on what I can do/use to run cucumber scenarios in parallel on Windows? So far, I've tried (with the follow findings):
WatirGrid
Have to use Ruby threads to actually run in "parallel".
This forces us to wrap the browser object in a thread, and therefore
un-reachable once the thread block closes. (Can't pass Browser object
to cucumber environment)
Hydra:
Need SSH (and public-key) access to remote boxes (ie. No Windows)
Selenium Grid:
Super heavy and can't find clear Cucumber testing path
TestJour:
Requires Bonjour (which isn't available for Windows)
Re Watirgrid ...
I've since added an iterate method which can be passed a block of watir code to execute against remote browser objects. So the browser objects become reusable between steps. An updated detailed cucumber example is here:
https://github.com/90kts/watirgrid/blob/master/examples/cucumber/step_definitions/example_steps.rb
Your cuke steps end up looking like this:
Given /^navigate to the portal$/ do
#grid.iterate {|browser| browser.goto "http://gridinit.com/examples/logon.html" }
end
When /^they enter their credentials$/ do
#grid.iterate do |browser|
browser.text_field(:name => "email").set "tim#mahenterprize.com"
browser.text_field(:name => "password").set "mahsecretz"
browser.button(:type => "submit").click
end
end
Then /^they should see their account settings$/ do
#grid.iterate do |browser|
browser.text.should =~ /Maybe I should get a real Gridinit account/
end
end
If you have any questions feel free to drop me a line. We also have a commercial implementation of watirgrid on EC2 available for beta at http://gridinit.com/public/examples so stay tuned for more updates with different test frameworks!
FYI the control / iterate helpers are in the latest version of watirgrid v1.1.2
Alternatively to do it in parallel with different scenarios on each of the providers, I would just have a support/env.rb that looks something like this:
require 'watirgrid'
require 'rspec/expectations';
ENV["GRID"] = 'true'
ENV["controller_uri"] = "druby://10.0.1.3:11235"
if ENV["GRID"] then
params = {}
params[:controller_uri] = ENV["controller_uri"]
params[:browser] = 'chrome' # type of webdriver browser to spawn
grid ||= Watir::Grid.new(params)
grid.start(:initiate => true, :quantity => 1, :take_all => true)
else
#browser ||= Watir::Browser.new :chrome
end
Before do |scenario|
#browser = grid.providers.first
end
at_exit do
grid.iterate do |browser|
browser.close
end
grid.release_tuples
end
Note I'm using :take_all => true to get exclusive access to a provider and releasing it back to the grid at_exit ... I would then call my scenarios from a separate test runner using the CLI, maybe wrapped in a bash or DOS script e.g.
cucumber features --name "Name of scenario 1"
cucumber features --name "Name of scenario 2"
cucumber features --name "Name of scenario 3"
...
etc

How can I change ruby log level in unit tests based on context

I'm new to ruby so forgive me if this is simple or I get some terminology wrong.
I've got a bunch of unit tests (actually they're integration tests for another project, but they use ruby test/unit) and they all include from a module that sets up an instance variable for the log object. When I run the individual tests I'd like log.level to be debug, but when I run a suite I'd like log.level to be error. Is it possible to do this with the approach I'm taking, or does the code need to be restructured?
Here's a small example of what I have so far.
The logging module:
#!/usr/bin/env ruby
require 'logger'
module MyLog
def setup
#log = Logger.new(STDOUT)
#log.level = Logger::DEBUG
end
end
A test:
#!/usr/bin/env ruby
require 'test/unit'
require 'mylog'
class Test1 < Test::Unit::TestCase
include MyLog
def test_something
#log.info("About to test something")
# Test goes here
#log.info("Done testing something")
end
end
A test suite made up of all the tests in its directory:
#!/usr/bin/env ruby
Dir.foreach(".") do |path|
if /it-.*\.rb/.match(File.basename(path))
require path
end
end
As you noted you're going to need to set something in the suite.
Something like the following can be used in the setup method. Just call MyLog.setInSuite in your suite and it'll set the level to INFO on setup.
module MyLog
##use_info = false
def MyLog.setInSuite()
##use_info = true
end
def setup
#log = Logger.new(STDOUT)
if (##use_info)
#log.level = Logger::INFO
else
#log.level = Logger::DEBUG
end
end
end
Hmm. I think the way to do it is to change the logging module to test an environment variable, say TEST_SUITE and set the logging level to info if it is set, and debug if it is not.
Then update your test suite to set the TEST_SUITE environment variable at the top, and unset it at the bottom.
Seems a bit clunky, so I'd be interested to see if anyone else has any other ideas.

Resources