Friday, 20 June 2008

Asserts

In this blog I’m going to show you how to apply asserts to your scripts using ruby’s built in ‘test/unit’ library. Some people are not quite sure what an assert is in programming terms but it is very simply asserting an outcome. So with this example were going to work with I am making an assertion on the expected result returned by a class. The class in our example will simply return the result of two numbers added together. So let’s look at our class that adds the numbers together first:

**Start of code
01 class Plus2
02 def initialize(a, b)
03 @ = a
04 @b = b
05 end
06
07 def add_up
08 begin
09 result = @a + @b
10 if result = = 4
11 return result
12 else
13 return 0
14 end
15 rescue
16 return 0
17 end
18 end
**End of code

We’ll save the file as ‘scriptplus2.rb’
This script simply accepts two integer values adds them together and returns the result.Line 02 to 05 uses the standard initialize method to receive our two integer values.Line 09 adds our values together and stores the new value into our variable ‘result’.Line 10 test the value of result to see if we have the value of 4, if we do we return this value if not we return a value of zero.
So lets look at our calling class:

**Start of code
01 Require “scriptplus2”
02 Require “test/unit”
03
04 class AssertTest < Test::Unit::Case
05
06 Def test_a
07 Myobject = Plus2.new(2,2)
08 assert_same(4, myobject.add_up())
09 end
10 end
**End of code

We’ll save this file as assert.rb
Line 01 requires our first file.
Line 02 requires ruby’s ‘test/unit’ library allowing our asserts to work
Line 04 defines our class ‘AssetTest’ but also attaches to our class the ‘test/unit’ methods with the ‘< Test::Unit::Case’ statement.
Line 06 defines our method. Two things to note here
Note 1: ‘test_’ ('test' followed by an underscore) must be at the start of any method name you want included in assertion testing. Any methods that do not start with the ‘test_’ identifier will not be included in assertions. This can be useful if you have methods that you do not wish to be included in assertion tests but are required by your class, setup methods etc.
Note 2: Your methods will be executed in alphabetical order. So if you have three methods defined as 'test_a', 'test_b' & 'test_c' no matter what order you place them in your class, 'test_a' will run first followed by 'test_b' & finally 'test_c'.
Line 07 creates an object of our class ‘Plus2’ from our ‘scriptplus2.rb’ file and passes to the ‘initialize’ method our two integer values.
Line 08 essentially calls our ‘add_up’ method but wrapped around our call is the asset_same method. Let’s look at this line in detail to see exactly what’s going on. What were saying here is I assert that the reply I get back from the ‘add_up’ method should be the value of 4. If 4 is returned the program ends and will report the following:
1 test, 1 assertion, 0 failures, 0 errors
If we change line 07 to ‘Myobject = Plus2.new(2,1)’ what will happen is our method will return zero because 2 + 1 = 3 and the assert report will now read:
1 test, 1 assertion, 1 failure, 0 errors

This gives a very simple example of one type of assertion but I hope it will give you a starting point from which you can develop further assertion tests.

Saturday, 7 June 2008

Activate a text area within a web page

Clicking a text area within a web page was proving rather difficult using just the standard controls within water i.e. click event etc which you use for objects like buttons & text boxes.  The area was contained within 2 iframes, a table object and finally a paragraph object p which was part of a document. To activate the area manually you simply click the area with the mouse and this activated not only the text area for adding text directly to the page but also activated the control toolbar which was otherwise grayed out stopping you from using many of the pages features. But this task proved very difficult to emulate within code. The final code which worked was used like a reference map to drill down onto the required paragraph and then using not one but three fire events finally emulated the simple mouse click. Here is the code with full comments as to what’s happening:

#First create a variable ‘$mainWindow to hold the first iframe reference
$mainWindow = $browser.frame(:id, frame1)
#Now create a new variable $mainContent to hold the first reference and reference the next iframe.
$mainContent = $mainWindow.frame(:id, frame2)
#Having got these references  set the focus to its associated document body
$mainContent.document.body.focus
#Now set a reference to the first text within the document area using index (i.e. The first paragraph, p)
$firstParagraph = $mainContent.p(:index, 1)
#Set focus on this paragraph
$firstParagraph.focus
#Now fire the events of ‘onmousedown’, ‘onmouseup’ & ‘onclick’. You need to fire all of these events
$firstParagraph.fire_event("onmousedown")
$firstParagraph.fire_event("onmouseup")
$firstParagraph.fire_event("onclick")

And that’s it. The text area was activated which in turn activated the main toolbar to access other features. Certainly not so straight forward as I first thought.

Wednesday, 4 June 2008

OOP with Ruby

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.

Sunday, 1 June 2008

Intro ...

This blog will mainly concentrate on my discoveries\findings and ramblings relating to testing with Ruby\Watir programming scripts.
Firstly a brief overview of myself and why this blog is being set up.

I come from a programming background having graduated studying in ‘C’, still to me the most elegant programming language. Shortly after graduating I moved into Windows programming with ‘Visual Basic 4’ and over the years that followed migrated to and programmed in ‘VB5’, ‘VB6’ and then ‘VB.net’. Also I have been dabbling with C#.

Whist I was working within the telecommunication industry I got my first taste of ‘testing’ but not as you might say in a conventional way. I was tasked with writing the front end of a hardware component testing program. The front end using ‘VB6’ whilst under the hood being written in ‘C\C++’, this turned out to be the most demanding program I had ever written. Whilst I concentrated on the UI I was teamed up with a very talented embedded electronics software engineer. To cut a long story short over the coming 2 years we produced a completely modular self scaling and dare I say user friendly suite of test programs that could adapt and mould not only to the company’s current hardware platform but also to future designs not even yet conceived. Hence when an opportunity came about to move into the testing environment on a more permanent basic I took it. Since that move which happened late 2006 I have more recently started to use the Ruby\Watir programming combination to automate test scripts. This blog is going to be about my successes and failures as I get to grips with this technology.