This blog describes a more OOP way of working within Ruby\Watir when using your own modules. Firstly we'll see how a module can work in a more traditional way. So here is our basic module:
**Start of File
=begin
This module directs the browser object to the Google home page
=end
begin
$browser.goto("www.google.co.uk")
$browser.wait
$log.info("Successfully navigated to Google")
rescue
$log.debug("Failed to navigate to Google")
end
**End of file
We'll save this as 'urlPath.rb'. This module when called from our calling program will simply
point our browser to Google.co.uk. So now we'll look at our calling program:
** Start of File
=begin
This module is the calling program for our 'urlPath.rb' module
=end
#Include all required files
#Create the logging object
require "Logger"
require "watir"
include Watir
#Create the working object
$browser = IE.new
Watir::IE.attach_timeout = 10.0
#Create my logging object
time = Time.now.strftime("%m %d %Y %H %M %s")
$log = Logger.new("NEWPAGE_#{time}.log")
$log.level = Logger::DEBUG
$log.datetime_format = "%d-%b-%Y %H:%M:%S"
$log.info("Core Logger starting...")
#Call our module
load "urlPath.rb"
#Carry on with the rest of the program ...
$browser.close
**End of File
We'll save this as 'Calling.rb'. This module will call our previous module ‘urlPath.rb’.
Hopefully this is all very straightforward. In our calling program we create and acquire our logger and watir objects as usual. The only working line of code is to load in our urlPath.rb module. Notice the use of the global variables $browser & $log, this just allows us to span across our modules.
This works fine. But there are restrictions. If I wanted to pass or receive arguments to my urlPath.rb module I can't. All a can do is call/load the module, let it do its own thing and carry on with the rest of the program upon its return. If we get a problem within the module it gets reported to the log file but what if depending on the type of error we get will affect how I want the rest of the program to respond, from ignoring the error to shutting down the program. In this instance I don’t have that control.
The answer is to use a module defined as a class. Here is the same program but written in a more OOP way:
** urlPath.rb
**Start of File
=begin
This module directs the browser object to the Google home page
=end
class URLPATH
def initialize(url)
@clsURL = url
End
def url()
begin
$browser.goto(@clsURL)
$browser.wait
return false
rescue
return true
end
end
end
**End of File
So let’s discuss the changes to our urlPath.rb file. First we have wrapped it in a class module called 'URLPATH'. Within this class we have two functions called initialize & url. This class takes one argument which is automatically passed to the class on intialisation, the url we wish to go to.
Also the class now returns a boolean value of false if all goes well and true if an error occurs. So the immediate benefit of turning our module into a class module is we can now send and receive arguments to the class. Other than that the class is no different from the previous module.
Now let’s look at our calling program changes:
** calling.rb
**Start of File
=begin
This module is the shell program for calling our 'urlPath' module
=end
#Include all required files
#Create the logging object
require "urlPath"
require "Logger"
require "watir"
include Watir
#Create the working object
$browser = IE.new
Watir::IE.attach_timeout = 10.0
#Create my logging object
time = Time.now.strftime("%m %d %Y %H %M %s")
$log = Logger.new("NEWPAGE_#{time}.log")
$log.level = Logger::DEBUG
$log.datetime_format = "%d-%b-%Y %H:%M:%S"
$log.info("Core Logger starting...")
def CloseDown
#Do any tidy up code here
$log.debug("Closing down program ...")
$browser.close
#Terminate the program
exit
end
#Create our class instance and pass in the url path.
myObject = URLPATH.new("www.google.co.uk")
#Call our url function within our class (also note our expected return value into ‘result’
result = myObject.url()
if result
$log.debug("URLPath module - FAILED")
CloseDown()
else
$log.info("URLPath module - PASSED")
end
#Carry on with the rest of the program ...
$browser.close
**End of File
Firstly the main changes are the use of a require statement at the beginning of the program to acquire our module instead of the ‘load’ command previously. Also we have added a function called 'CloseDown' to handle a returned error state from our class. Finally the way we create\call our class (module) is now very different. But apart from these changes the code remains the same as before.
Now we must create our own object to be associated with the class ‘URLPATH’ within the ‘urlPath.rb’ module. This object I’ve called 'myObject' as in the following line:
myObject = URLPATH.new("www.google.co.uk")
Now on creating our object we automatically send the url path to the initialize function within our class. We now reference our class function url with ‘myObject’ with the following line to invoke it:
result = myObject.url()
One important point to remember is if we have other functions defined within our class we can also get access to these with the same ‘myObject’.
If there was a problem and our error trap is invoked a true value is returned we handle it in this simple example by logging the fact and closing down our program in a correct and proper manner by calling the 'CloseDown' function. If all is well and we receive back a false value we again log this fact and carry on with the rest of the program. Here we are using only one call to a function within our class but we could be calling several more functions all of which can all be handled in exactly the same manner. This approach gives us more flexibility and control over the modules\classes we write.


0 comments:
Post a Comment