Tuesday, February 22, 2011

What is TRM?

Web Application Testing in Ruby: What is stub?

TRM means Test Responsibility Matrix.

TRM: --- It indicates mapping between test factors and development stages...

Test factors like:
Ease of use, reliability, portability, authorization, access control, audit trail, ease of operates, maintainable... Like dat...
Development stages...
Requirement gathering, Analysis, design, coding, testing, and maintenance

Monday, February 21, 2011

What is release notes?

Web Application Testing in Ruby: What is stub?

It's a document released along with the product which explains about the product. It also contains about the bugs that are in deferred status.

What is internationalization Testing?

Web Application Testing in Ruby: What is stub?

Software Internationalization is process of developing software products independent from cultural norms, language or other specific attributes of a market

What is stub?

Web Application Testing in Ruby: What is bidirectional traceability?
Stub is a dummy program or component, the code is not ready for testing, it's used for testing...that means, in a project if there are 4 modules and last is remaining and there is no time then we will use dummy program to complete that fourth module and we will run whole 4 modules also. The dummy program is also known as stub

What is bidirectional traceability?

Web Application Testing in Ruby: What is agile testing?
What is bidirectional traceability?

Bidirectional traceability needs to be implemented both forward and backward (i.e., from requirements to end products and from end product back to requirements).
When the requirements are managed well, traceability can be established from the source requirement to its lower level requirements and from the lower level requirements back to their source. Such bidirectional traceability helps determine that all source requirements have been completely addressed and that all lower level requirements can be traced to a valid source.

What is agile testing?

Web Application Testing in Ruby: What is Recovery testing?

What is agile testing?
What is agile testing?

Agile testing is used whenever customer requirements are changing dynamically

If we have no SRS, BRS but we have test cases does you execute the test cases blindly or do you follow any other process.

Test case would have detail steps of what the application is supposed to do.
1) Functionality of application.
2) In addition you can refer to Backend, is mean look into the Database. To gain more knowledge of the application.

What is Recovery testing?

Web Application Testing in Ruby: What is Recovery testing?

Recovery Testing is the testing which is used to find how
well the application will get recover from crashes.

What is Recovery testing?

Evaluates the contigency features are built in the
application for handling interruptions and to return to
specific check points. This test also assures that disaster
recovery if possible.

Wednesday, February 9, 2011

Excel Interface Class

Summary
This ruby class provides simple methods for reading and writing data records to and from Excel spreadsheets. This data can then be easily used to create data-driven Watir tests. This class hides the complexities of directly using ruby's win32ole library to interface with Excel.

Features
Excel Data can be identified/located on any sheet using and either a "Range" (e.g. "A1:C20") or dynamically by searching for a specific text label above a data range
Excel Data formated as rows of records or as columns of records can easily be read
Data can be read in as an Array of Hashes (using headers as keys), a plain 2D Array, or a simple Hash of key-value pairs.
If the excel data file is already open, this class will simply attach to the open workbook and read its data instead of trying to re-open the file.
[6/22/07] Support adding and removing excel worksheets
[6/22/07] Support for ordered hashes, and writing them back to an excel file.
[6/25/07] Uploaded the RDOC documentation for the XLS class see XLS_doc.zip
[7/11/07] Made all get methods more flexible in how the range is specified (they now accept a string representing a literal range,a Named Range in the workbook, or a text label above a contiguous range of cells with data). This allowed me to simplify/shorten method names and to remove Redundant methods.

Web Application Testing in Ruby: How to wait in Watir?

Web Application Testing in Ruby: How to wait in Watir?

1 - New Windows
Navigating to a new page with the existing IE window will not require you to define any special behavior. However, if you perform an action that brings up a secondary page (pop-up) you will need to define some code to wait on it's existence. Luckily, if you can deal with pop-ups with the "attach" method, there is already an implicit wait in the attach method. If you have a modal dialog box or other windows related dialog box (Security Alert Box, Login, File Download, etc.) you will need to create your own wait methods. See this section for more info.

2 - Objects that depend on Javascript to show up
Sometimes IE thinks it's done before everything is loaded. Unfortunately, IE#wait doesn't always work here because it exits whenever IE thinks it's done. So, if this is your problem, you will need to tell Watir to wait. There are several ways to solve this, here are two.

If you want to wait forever, consider the following:

sleep 1 until ie.text.include? "new results are loaded"
This code will keep sleeping until the text "new results are loaded" appears on the page. However, you may not want to wait forever. Using the following code will wait; for the text "new results are loaded" to appear on the page OR 60 seconds, whichever comes first.

wait_until {ie.text.include? "new results are loaded"}
Sometimes you need to wait for something to happen in the Application under test before you interact with it. Sleep statements are hardcoded and lock you down into a certain number of seconds before moving through your test. To avoid that, we've written a polling mechanism in the latest versions of Watir - the wait_until method.

An example might be that you're loading the Google home page and for some reason it's taking time to load. Here's a basic contrived script with a sleep statement.

require 'watir'

browser = Watir::Browser.start('http://www.google.com')
sleep 5 # we need to wait for the page to load and on a subjective basis I've chosen 5 seconds which works on my machine
browser.text_field(:name, 'q').set('ruby poignant')
....
Unfortunately the sleep is hardcoded and doesn't work for anyone else on my team who have slower network connections, my connection has gotten faster, but it still waits for 5 seconds before setting the text field.

Watir has a Watir::Waiter class with a wait_until method that can poll for a certain condition to return true before continuing on or erroring out. By default it checks the condition every half second up until 60 seconds. So I rewrite my code to look like this:

require 'watir'
browser = Watir::Browser.start('http://www.google.com')
# In this case all I care about is the text field existing, you could
# check title, text, anything you're expecting before continuing
Watir::Waiter::wait_until { browser.text_field(:name, 'q').exists? }
browser.text_field(:name, 'q').set('ruby poignant')
...
It now works for me with a half second delay, but also works for the other members of my team who have network delays up to a minute. If you're considering using sleep, use wait_until instead. It will make your test code more resilient to timing issues in those cases where you really need to use it.

3 - Handling asynchronous javascript / AJAX
if you include asynchronous JS in your definition of done, you'll need to code around that specifically. There's an open feature request to have Watir's wait method track XHRs and timers that are launched when the page is loaded, and wait for them as well. That may be tricky to do though, and with an all-volunteer project, it really depends on someone making the time to do it.

In lieu of that, one option is having the application keep track if XHRs and timers that it kicks off, and setting the some value to true when they are all complete. For example:

def wait_until_loaded(timeout = 30)
start_time = Time.now
until (however_your_application_reports_its_loaded == 'true') do
sleep 0.1
if Time.now - start_time> timeout
raise RuntimeError, "Timed out after #{timeout} seconds"
end
end
end
A simpler option is:

tries = 0
until browser.link(:text, /link_to_wait_for/).exists? do
sleep 0.5
tries += 1
end
browser.link(:text, /link_to_wait_for/).click
end
Another option is to retry until timeout or no exception is raised.

def rescue_wait_retry(exception = Watir::Exception::UnknownObjectException, times = 10, seconds = 2, &block)
begin
return yield
rescue exception => e
puts "Caught #{exception}: #{e}. Sleeping #{seconds} seconds." if $DEBUG
sleep(seconds)
@ie.wait
if (times -= 1)> 0
puts "Retrying... #{times} times left" if $DEBUG
retry
end
end
yield
end

@ie.link(:url, %r|confirmdelete\.action\?educationId|).click #This starts some ajax stuff
rescue_wait_retry { @ie.button(:id, 'form_0').click }
Not sure about this one but this is a good introduction to the problem.

Also, from the thread "[wtr-general] SUMMARY: Enable/disable JS support in IE"

Q - How to check from watir code whether web page was reloaded or it was updated dynamically withJS.
A - Not so easy to implement for HCOM application due to a lot of ajax stuff. The following code should work when JS is disabled, plus we can pass additional condition to check here (e.g. waiter for object appearance on the page). Note: $ie is global IE instance in our framework. Also I think that we need to use something like click_no_wait method to reload the page, otherwise IE.wait() method won't let us do the check until page is ready. What I was asking here is how to check that page is reloading rather than just some elements on the page are updated with JS.

class Page
def loading?(additionalCondition = false)
if $ie.ie.busy || ($ie.ie.readyState != 4) || additionalCondition
true
else
false
end
end
end
4 - Yourself while you watch a script execute
Maybe you are watching the script execute and you just want to slow things down for troubleshooting reasons. Of course, there is always the venerable (and oft overused) "sleep" method. Using "sleep( x )" will cause the script to pause for x seconds.

If, however, you are annoyed by the slowness of your script, you can always make it faster:

ie = Watir::IE.new
ie.speed = :fast

or

ie = Watir::IE.new
ie.speed = :zippy
See this for more information.

click_no_wait
Information here about what this method is all about.

Continuing testing if IE refuses to load a page
When IE.attach does not find a window it throws a NoMatchingWindowFoundException. You can catch the exception instead of letting watir exit your tests. At this point you can build some 'recovery' if you need it or simply continue or exit your test explicitly after logging some test data.

require "watir"

begin
@ie = Watir::IE.attach(:url , /Webpage Dialog/) #let's say the window does not exist on the desktop
rescue Watir::Exception::NoMatchingWindowFoundException => e
puts "Failed to find new pop up window! #{e}"
# you can now recover or exit or continue
end
When IE.goto is invoked it implicitly waits for the page to load and runs any registered @error_checkers. If you don't have them added to browser then you can explicitly call check_for_http_errors. On HTTP errors encountered the Exception will be thrown. You can rescue the exception and continue with your test and recover or just exit after logging some test data.

require 'watir'
@ie = Watir::IE.new #start new browser window
@ie.goto 'http://asdf asdf.com' #navigation to this page will load Can Not Find Server page #notice the space in url string

begin
@ie.check_for_http_error # will throw Exception
rescue Watir::Exception::NavigationException => e #catch the Exception
puts "Page did not load: #{e}" # => 'Cannot find server or DNS Error'
# you can now recover or exit or just continue
end

# OR you can register error_checker which will be called when goto is invoked
require 'watir/contrib/page_checker'
@ie.add_checker(PageCheckers::NAVIGATION_CHECKER)

begin
@ie.goto "http://marekj.com/asdfasdfasdfa"
rescue Watir::Exception::NavigationException => e #catch the Exception
puts "Page did not load: #{e}" # => 'HTTP 404 - File not found'
# you can now recover or exit or just continue
end

How to wait in Watir?

Watir does not wait for new page to load, except:

when you "attach" to an existing

window
use the "click" method
"set" or "clear" radio buttons or checkboxes
when you select an item in a select list
when you clear a text field
when you "goto" a new page
when you "submit" a form
when you "back", "forward" or "refresh" the browser
when you "fire_event" on any element


ie = Watir::IE.attach(:title, 'My Window')
# no need to wait, ie.wait called implicitly
ie.link(:id, 'mylink').click
# no need to wait, ie.wait called implicitly
assert(ie.link(:id, 'mynewlink).exists?)

"Watir is deterministic. Watir does not wait X seconds. It waits until the page is loaded. Period."

How do I use Ruby for shell scripting?

Dir['*.rb'] #basic globs
Dir['**/*.rb'] #** == any depth of directory, including current dir.
#=> array of relative names

File.expand_path('~/file.txt') #=> "/User/mat/file.txt"
File.dirname('dir/file.txt') #=> 'dir'
File.basename('dir/file.txt') #=> 'file.txt'
File.join('a', 'bunch', 'of', 'strings') #=> 'a/bunch/of/strings'

__FILE__ #=> the name of the current file
Also useful from the stdlib is FileUtils

require 'fileutils' #I know, no underscore is not ruby-like
include FileUtils
# Gives you access (without prepending by 'FileUtils.') to
cd(dir, options)
cd(dir, options) {|dir| .... }
pwd()
mkdir(dir, options)
mkdir(list, options)
mkdir_p(dir, options)
mkdir_p(list, options)
rmdir(dir, options)
rmdir(list, options)
ln(old, new, options)
ln(list, destdir, options)
ln_s(old, new, options)
ln_s(list, destdir, options)
ln_sf(src, dest, options)
cp(src, dest, options)
cp(list, dir, options)
cp_r(src, dest, options)
cp_r(list, dir, options)
mv(src, dest, options)
mv(list, dir, options)
rm(list, options)
rm_r(list, options)
rm_rf(list, options)
install(src, dest, mode = , options)
chmod(mode, list, options)
chmod_R(mode, list, options)
chown(user, group, list, options)
chown_R(user, group, list, options)
touch(list, options)

Friday, February 4, 2011

Watir-WebDriver in three browsers

These three browsers seem to work very similarly, but obviously Internet Explorer will only run on Microsoft Windows.

view sourceprint?01 require "rubygems"

02 require "watir-webdriver"

03 require "watir-webdriver/extensions/wait"

04 b = Watir::Browser.new :chrome

05 b.goto "www.google.com"

06 b.text_field(:name => "q").set "Watir-WebDriver"

07 b.button(:name => "btnG").click

08 b.div(:id => "resultStats").wait_until_present

09 puts "Displaying page: '#{b.title}' with results: '#{b.div(:id => "resultStats").text}'"

10 b.close

Watir Framework

A Watir framework that object models your AUT and uses Rspec Story Runner aidy dot lewis at googlemail dot com

gem install rspec

Run example from:
watirFramework\runner\gmail.rb

(you will need to sign out of gmail)

watirFramework.zip you want this mail me...or comment on this post


The rspecReports zip contains js and css to colour your HTML reports

Red is a fail
Green a pass
Yellow means pending

eg.
cd watirFramework\runner
ruby gmail.rb -fh: > "C:\rspec_reports\gmail.htm"

rspecReports.zip
you want this mail me...or comment on this post


Labels parameters

Labels

Is Ruby is a Scripting Language or Compiled Language?

In general, programming languages fall into one of two
categories: they're either compiled languages or scripting
languages. Let's explore what each of those terms means, and
understand the differences between them.

Compiled Languages: The language in which you write an
application is not actually something that your computer
understands. Your code needs to be translated into bits and
bytes that can be executed by your computer. This process of
translation is called compilation, and any language that
requires compilation is referred to as a compiled language.
Examples of compiled languages include C, C#, and Java.

For a compiled language, the actual compilation is the final
step in the development process. You invoke a compiler --
the software program that translates your final
hand-written, human-readable code into machine-readable code
-- and the compiler creates an executable file. This final
product is then able to execute independently of the
original source code.

Thus, if you make changes to your code, and you want those
changes to be incorporated into the application, you must
stop the running application, recompile it, then start the
application again.

Scripting Languages: On the other hand, a scripting language
such as Ruby, PHP, or Python, relies upon an application's
source code all of the time. Scripting languages don't have
a compiler or a compilation phase per se; instead, they use
an interpreter -- a program that runs on the web server --
to translate hand-written code into machine-executable code
on the fly. The link between the running application and
your hand-crafted code is never severed, because that
scripting code is translated every time it is invoked -- in
other words, for every web page that your application renders.

As you might have gathered from the name, the use of an
interpreter rather than a compiler is the major difference
between a scripting language and a compiled language.

The Great Performance Debate: If you've come from a
compiled-language background, you might be concerned by all
this talk of translating code on the fly -- how does it
affect the application's performance?

These concerns are valid -- translating code on the web
server every time it's needed is certainly more expensive,
performance-wise, than executing pre-compiled code, as it
requires more effort on the part of your machine's
processor. The good news is that there are ways to speed up
scripted languages, including techniques such as code
caching and persistent interpreters. However, both topics
are beyond the scope of this book.

There's also an upside to scripted languages in terms of
performance -- namely, your performance while developing an
application.

Imagine that you've just compiled a shiny new Java
application, and launched it for the first time ... and then
you notice a typo on the welcome screen. To fix it, you have
to stop your application, go back to the source code, fix
the typo, wait for the code to recompile, and restart your
application to confirm that it is fixed. And if you find
another typo, you'll need to repeat that process again.
Lather, rinse, repeat.

In a scripting language, you can fix the typo and just
reload the page in your browser -- no restart, no recompile,
no nothing. It's as simple as that.

Tuesday, February 1, 2011

How to Create watir Frame work : Admin Module.rb

Web Application Testing in Ruby: How to Create watir Frame work : Customer Module.rb
require 'test/unit'

02 include Test::Unit::Assertions

03

04 module Admin

05 TITLE = 'ADMINISTER Pragprog Books Online Store'

06 URL = 'http://localhost:3000/admin/'

07

08 def Admin.log_on(browser, username, password)

09 browser.goto(URL)

10 if browser.link(:text,'Log out').exist? then #if already logged in

11 browser.link(:text,'Log out').click

12 end

13 browser.text_field(:id, 'user_name').set username

14 browser.text_field(:id, 'user_password').set password

15 browser.button(:value, ' LOGIN ').click

16 if browser.div(:id, 'notice').exist? then

17 return false,browser.div(:id, 'notice').text

18 else

19 return true,''

20 end

21 end

22

23 def Admin.ship_items(browser, name)

24 browser.goto(URL)

25 browser.link(:text, 'Shipping').click

26 num_orders = 0

27 index = 0

28 browser.form(:action,'/admin/ship').divs.each do |div|

29 if div.class_name == "olname"

30 index+=1

31 if div.text == name then

32 browser.form(:action,'/admin/ship').checkbox(:index, index).set

33 num_orders+=1

34 end

35 end

36 end

37

38 browser.button(:value, ' SHIP CHECKED ITEMS ').click

39

40 if num_orders == 1 then

41 assert_equal(browser.div(:id,"notice").text, "One order marked as shipped","Correct notice")

42 elsif num_orders > 1 then

43 assert_equal(browser.div(:id,"notice").text, "#{num_orders} orders marked as shipped","Correct notice")

44 end

45 return true, num_orders.to_s

46 end

47

48 end

How to Create watir Frame work : Customer Module.rb

Web Application Testing in Ruby: How to Create watir Frame work : Test Driver tc_main.rb

require 'test/unit'

002 include Test::Unit::Assertions

003

004 module Customer

005

006 TITLE = 'Pragprog Books Online Store'

007 URL = 'http://localhost:3000/store/'

008

009 # Description:: Adds a book named 'book_title' to cart

010 def Customer.add_book(browser, book_title)

011 browser.goto(URL)

012 # Check if title is already in cart - so we can check it was added correctly

013 browser.link(:text,'Show my cart').click

014 prev_cart_count = 0

015 prev_cart_total = 0.00

016 if not browser.div(:text,'Your cart is currently empty').exist? then

017 # We have a non-empty cart

018 for row in browser.table(:index,1)

019 if row[2].text == book_title then

020 prev_cart_count = row[1].text.to_i

021 break

022 end

023 end

024 prev_cart_total = browser.cell(:id, 'totalcell').text[1..-1].to_f #remove $ sign

025 browser.link(:text, 'Continue shopping').click

026 end

027

028 found = false

029 book_price = 0.00

030 1.upto(browser.divs.length) do |index|

031 if (browser.div(:index,index).attribute_value('className') == 'catalogentry') and (browser.div(:index,index).h3(:text,book_title).exists?) then

032 book_price = browser.div(:index,index).span(:class, 'catalogprice').text[1..-1].to_f #remove $ sign

033 browser.div(:index,index).link(:class,'addtocart').click

034 found = true

035 break

036 end

037 end

038 if not found then

039 return false,'Could not locate title in store'

040 end

041

042 new_cart_count = 0

043 for row in browser.table(:index,1)

044 if row[2].text == book_title then

045 new_cart_count = row[1].text.to_i

046 break

047 end

048 end

049 new_cart_total = browser.cell(:id, 'totalcell').text[1..-1].to_f # remove $ sign

050 assert_equal(new_cart_count,(prev_cart_count+1), "Ensure that new quantity is now one greater than previously")

051 assert_equal(new_cart_total,(prev_cart_total + book_price), "Ensure that new cart total is old cart total plus book price")

052 browser.link(:text, 'Continue shopping').click

053 return true,new_cart_total

054 end

055

056 def Customer.check_out(browser, customerName, customerEmail, customerAddress, customerPaymentMethod)

057 browser.goto(URL)

058 browser.link(:text,'Show my cart').click

059 if browser.div(:text,'Your cart is currently empty').exist? then

060 return false,'Your cart is currently empty'

061 end

062 browser.link(:text,"Checkout").click

063 browser.text_field(:id, 'order_name').set(customerName)

064 browser.text_field(:id, 'order_email').set(customerEmail)

065 browser.text_field(:id, 'order_address').set(customerAddress)

066 begin

067 browser.select_list(:id, 'order_pay_type').select(customerPaymentMethod)

068 rescue Watir::Exception::NoValueFoundException

069 flunk('Could not locate customer payment method in drop down list: '+customerPaymentMethod)

070 end

071 browser.button(:name, 'commit').click

072 if browser.div(:id,'errorExplanation').exist? then

073 error = ''

074 1.upto(browser.div(:id,'errorExplanation').lis.length) do |index|

075 error << (browser.div(:id,'errorExplanation').li(:index,index).text + ",")

076 end

077 browser.link(:text,'Continue shopping').click

078 return false, error

079 end

080 assert_equal(browser.div(:id,'notice').text, 'Thank you for your order.',"Thank you for your order should appear.")

081 return true,''

082 end

083

084 def Customer.empty_cart(browser)

085 browser.goto(URL)

086 browser.link(:text,"Show my cart").click

087 if browser.div(:text,"Your cart is currently empty").exist? then

088 assert('Cart was never empty')

089 else

090 browser.link(:text,'Empty cart').click

091 assert_equal(browser.div(:id, 'notice').text,'Your cart is now empty')

092 end

093 return true,''

094 end

095

096 def Customer.check_cart_total(browser, exp_total)

097 browser.goto(URL)

098 browser.link(:text,'Show my cart').click

099 if browser.div(:text,'Your cart is currently empty').exist? then

100 return false,'Your cart is currently empty'

101 end

102 act_total = browser.cell(:id, 'totalcell').text[1..-1].to_f

103 assert_equal(act_total,exp_total.to_f,"Check that cart total is as expected.")

104 return true,act_total

105 end

106 end

How to Create watir Frame work : Test Driver tc_main.rb

Web Application Testing in Ruby: How to Create watir Frame work ?


$:.unshift File.join(File.dirname(__FILE__), ".", "lib")

002 require 'watir'

003 require 'roo'

004 require 'test/unit'

005 require 'customer'

006 require 'admin'

007 $stdout = File.new('log.txt',File::WRONLY|File::APPEND|File::CREAT)

008 $stderr = File.new('log.txt',File::WRONLY|File::APPEND|File::CREAT)

009

010 class TC_WatirMelon < Test::Unit::TestCase

011 @@colmap = {:module_name=>0, :method_name=>1, :comments=>2, :exp_outcome=>3, :exp_error=>4, :first_param=>5}

012 @@ss_format = ARGV[0]

013 @@specified_browser = ARGV[1]

014

015 def setup

016 puts "[Starting at #{Time.now}]\n"

017 case @@ss_format

018 when "excel"

019 @ss = Excel.new("watirmelon.xls")

020 when "wiki"

021 @ss = Excel.new("http://localhost:8080/download/attachments/2097153/watirmelon.xls")

022 when "gdocs"

023 @ss = Google.new("0AtL3mPY2rEqmdEY3XzRqUlZKSmM5Z3EtM21UdFdqb1E")

024 else

025 @ss = Openoffice.new("watirmelon.ods")

026 end

027 @ss.default_sheet = @ss.sheets.first

028 case @@specified_browser

029 when "firefox"

030 Watir::Browser.default = 'firefox'

031 @browser = Watir::Browser.new

032 else

033 Watir::Browser.default = 'ie'

034 @browser = Watir::Browser.new

035 @browser.speed = :zippy

036 @browser.visible = true

037 end

038 end

039

040 def test_run_sheet()

041 @ss.first_row.upto(@ss.last_row) do |row|

042 #Read row into array

043 line = Array.new

044 @ss.first_column.upto(@ss.last_column) do |column|

045 line << @ss.cell(row, column).to_s.strip

046 end

047

048 module_name = line[@@colmap[:module_name]]

049 if module_name != "Function" then #if not a header

050 method_name = line[@@colmap[:method_name]].downcase.gsub(' ','_') #automatically determine ruby method name based upon data sheet

051 exp_outcome = line[@@colmap[:exp_outcome]]

052 exp_error = line[@@colmap[:exp_error]]

053 first_param = @@colmap[:first_param]

054 required_module = Kernel.const_get(module_name)

055 required_method = required_module.method(method_name)

056 arity = required_method.arity() # this is how many arguments the method requires, it is negative if a 'catch all' is supplied.

057 arity = ((arity * -1) - 1) if arity < 0 # arity is negative when there is a 'catch all'

058 arity = arity-1 # Ignore the first browser parameter

059 unless arity == 0

060 parameters = line[first_param..first_param+(arity-1)]

061 else

062 parameters = []

063 end

064 begin

065 act_outcome, act_output = required_method.call(@browser, *parameters)

066 rescue Test::Unit::AssertionFailedError => e

067 self.send(:add_failure, e.message, e.backtrace)

068 act_outcome = false

069 act_output = e.message

070 end

071 if (exp_outcome == 'Success') and act_outcome then

072 assert(true, "Expected outcome and actual outcome are the same")

073 result = 'PASS'

074 elsif (exp_outcome == 'Error') and (not act_outcome) and (exp_error.strip! == act_output.strip!)

075 assert(true, "Expected outcome and actual outcome are the same, and error messages match")

076 result = 'PASS'

077 else

078 result = 'FAIL'

079 begin

080 assert(false,"Row: #{row}: Expected outcome and actual outcome for #{method_name} for #{module_name} do not match, or error messages do not match.")

081 rescue Test::Unit::AssertionFailedError => e

082 self.send(:add_failure, e.message, e.backtrace)

083 end

084 end

085 puts "###########################################"

086 puts "[Running: #{module_name}.#{method_name}]"

087 puts "[Expected Outcome: #{exp_outcome}]"

088 puts "[Expected Error: #{exp_error}]"

089 puts "[Actual Outcome: Success]" if act_outcome

090 puts "[Actual Outcome: Error]" if not act_outcome

091 puts "[Actual Output: #{act_output}]"

092 puts "[RESULT: #{result}]"

093 puts "###########################################"

094 end

095 end

096 end

097

098 def teardown

099 @browser.close

100 puts "[Finishing at #{Time.now}]\n\n"

101 end

102

103 end

How to Create watir Frame work ?

One common challenge I see over and over again is people figuring out how to design a logical and maintainable automated testing framework. I have designed quite a few frameworks for various projects, but one thing that has consistently been a win for me is purposely separating test case and test execution design.

It’s therefore logical that the design of my Watir framework deliberately separates test case design and test execution design so that:

■test case design is done visually in spreadsheets; and
■test execution design is done in ruby methods, because code is the most efficient and maintainable way.
Since I last published details about my framework on this blog, I have started doing assertions using the Test::Unit ruby library. The reasons I chose Test::Unit are:

■it is easy to ‘mix-in’ Test::Unit assertions into modules of ruby code using include Test::Unit::Assertions;
■it is included with ruby;
■ruby scripts with Test::Unit::TestCase are instantly executable, in my case, from SciTE;
■its assertions are easy to understand and use.
I have also made some other improvements to my framework code, including:

■the ability to specify browser types, and spreadsheet sources, as command line arguments (with defaults);
■logging test output to a file;
■no longer attaching to an open browser, the same browser instance is used completely for all tests (and elegantly closed at the end).
The main design has been kept the same, in that a spreadsheet (either excel, openoffice or Google Docs) contains tests grouped by functional area, which call a method in a particular module.

The great thing about my framework is that adding a new test is a matter of designing the test case, and then writing the ruby method: as the methods are called dynamically from the spreadsheet, no extra glue is needed!

Enough talk, here’s the code. The Google spreadsheet is here. You can find a .zip file of all the required files to run it here. It runs on the depot app, which you get here. You will need two gems: Watir (oh duh), and Roo.