<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-1708518509752812818</id><updated>2012-01-27T11:53:50.961+01:00</updated><category term='pitfalls'/><category term='VBScript'/><category term='call chain'/><category term='object repository'/><category term='winrunner'/><category term='tricks'/><category term='method chaining'/><category term='function calls'/><category term='secrets'/><category term='testnet'/><category term='transition'/><category term='desktop extension'/><category term='text editing'/><category term='arrays'/><category term='QTP'/><category term='add watch'/><category term='function pointer'/><category term='tooltips'/><category term='snel zoeken'/><category term='marktplaats'/><category term='API'/><category term='IBAN'/><category term='QTP10'/><category term='print'/><category term='mercury'/><category term='testability'/><category term='classes'/><category term='abstract data types'/><category term='coding'/><category term='book review'/><category term='data entry'/><category term='Reference Card'/><category term='dynamic class creation'/><category term='automated testing'/><category term='FileSystem'/><category term='code optimization'/><category term='regular expressions'/><category term='performance'/><category term='screenprinting'/><category term='utilities'/><category term='sprintf'/><category term='external functions'/><category term='scheduling'/><category term='keywords'/><title type='text'>Automated Chaos</title><subtitle type='html'>But remember: After automating a chaos, all you have is an automated chaos</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://automated-chaos.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://automated-chaos.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Bas M. Dam</name><uri>http://www.blogger.com/profile/07594616635957734329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>34</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1708518509752812818.post-6921306774239499615</id><published>2012-01-27T11:51:00.003+01:00</published><updated>2012-01-27T11:53:50.968+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='VBScript'/><category scheme='http://www.blogger.com/atom/ns#' term='QTP'/><category scheme='http://www.blogger.com/atom/ns#' term='FileSystem'/><title type='text'>Exist or be Created!</title><content type='html'>&lt;span style="font-family: Verdana, sans-serif;"&gt;Just encountered a collegue having difficulties ensuring if a folder exists. And if a folder does not exists then it has to be created in its full path, not only the lowest level folder. The code was bloated with if/then’s, instr(), instrrev() and left()/right() functions. Even the lowest level folder name was hardcoded.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: Verdana, sans-serif;"&gt;To help him out,&amp;nbsp;we could go for the fancy recursive solution to show off our 1337 programming skillz, but I decided to just do it with a&amp;nbsp;simple loop. Enjoy.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;Public Function EnsureFolder(fPath)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; dim fso, fols, fol, pathBuild&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; set fso=CreateObject("Scripting.FileSystemObject")&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; fols = split(fpath, "\")&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; For each fol in fols&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; If fol = "" Then exit for&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pathBuild = pathBuild &amp;amp; fol &amp;amp; "\"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; If Not fso.FolderExists(pathBuild) Then&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Call fso.CreateFolder(pathBuild)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; End If&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Next&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; EnsureFolder = pathBuild&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;End Function&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1708518509752812818-6921306774239499615?l=automated-chaos.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://automated-chaos.blogspot.com/feeds/6921306774239499615/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1708518509752812818&amp;postID=6921306774239499615' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/6921306774239499615'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/6921306774239499615'/><link rel='alternate' type='text/html' href='http://automated-chaos.blogspot.com/2012/01/exist-or-be-created.html' title='Exist or be Created!'/><author><name>Bas M. Dam</name><uri>http://www.blogger.com/profile/07594616635957734329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1708518509752812818.post-6997294998192257809</id><published>2011-12-13T21:40:00.003+01:00</published><updated>2011-12-13T21:44:00.266+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tricks'/><category scheme='http://www.blogger.com/atom/ns#' term='method chaining'/><category scheme='http://www.blogger.com/atom/ns#' term='VBScript'/><category scheme='http://www.blogger.com/atom/ns#' term='QTP'/><category scheme='http://www.blogger.com/atom/ns#' term='classes'/><category scheme='http://www.blogger.com/atom/ns#' term='coding'/><title type='text'>QTP and Method Chaining disclosed</title><content type='html'>With method chaining, you can chain object methods to an object in order to change it. It is the default paradigm of JQuery. After using it a while with JQuery, I figured out it is an extremely usefull method to use with QTP.&lt;br /&gt;&lt;br /&gt;If you use QTP long enough, you start to create your own function. But because VBScript doesn't allow optional parameters in homebrew functions, existing functions become clumsy with all types of parameters you don't use most of the time.&lt;br /&gt;I remember using functions like &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;findTextInTable(oTbl, txtToFind, startRow, endRow, startColumn, endColumn, byRef foundRow, byRef foundColumn)&lt;/span&gt; where each parameter could also be an array or contain signal characters. This results in a function call like this:&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;findTextInTable(myTable, array("account xyz", "!customer \d+"), 4, "", "", 5, foundRow, "")&lt;/span&gt;&lt;br /&gt;So far for self-explanatory code.&lt;br /&gt;&lt;br /&gt;When you use object chaining, you use only the parameters you need AND your code will become self explanatory. The code above will become:&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;xTable.addFindText("account xyz").addRegexFindText("customer \d+").startRow(4).endColumn(5).getFindRow(foundRow)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Of course this need some programming skills to build this correctly into a class, so let's start with an easy example: A string wrapper. When we create the class for the stringwrapper, we use functions for the methods. Functions can return primitives or objects, and with each object call, we return the object itself. You can also use "Get Property", but that will restrict you in the amount of parameters you can pass with your method to be exactly the same as the Let/Set Property.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Class cls_xString&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Private value_&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Public Function SetValue(v)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; value_ = v&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Set SetValue = me&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; End Function&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Public Default Function getValue()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; getValue = value_&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; End Function&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Public Function ToUpper()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; value_ = uCase(value_)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Set ToUpper = me&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; End Function&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Public Function Append(v)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; value_ = value_ &amp;amp; v&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Set Append = me&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; End Function&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Public Function Prepend(v)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; value_ = v &amp;amp; value_&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Set Prepend = me&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; End Function&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Public Function Surround(v)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; value_ = v &amp;amp; value_ &amp;amp; v&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Set Surround = me&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; End Function&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;End Class&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;We use another trick with the getValue; it is the default return value if the string class is called without a Set. To make the class usable globally, we need an initiator function that returns an object of class xString:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Public Function [new xString](initialValue)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Set [new xString] = new cls_xString&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; call [new xString].SetValue(initialValue)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;End Function&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;And now we can create some testcode:&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Dim myString &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Set myString = [new xString]("W00t, Method Chaining is really Working!")&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;msgbox myString.ToUpper.Prepend("(").Append(")").Surround("'")&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This will result in an editbox with text '(W00T, METHOD CHAINING IS REALLY WORKING!)'&lt;br /&gt;The method are parsed from left to right; first the string is transformed to uppercase, then prepended by (, appended by ) and finally surrounded by '.&lt;br /&gt;&lt;br /&gt;Other usage: &lt;br /&gt;- Narrowing down a collection and get a single object&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Set linkCollection = [new linkCollection](oPage)&amp;nbsp;&amp;nbsp;&amp;nbsp; ' Get all links from a page&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Set myLink = linkCollection.withRegexText(".*Help.*").Index(3)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Or do directly an action on that object:&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;linkCollection.withRegexText(".*Help.*").Index(3).Click&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;- Narrowing down collections and do actions on them:&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Set editCollection = [new editboxCollection](oPage)&amp;nbsp;&amp;nbsp;&amp;nbsp; ' Get all editboxes from a page&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;' Set all editboxes that are visible, enabled and empty with a value&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;editCollection.withProperty("visible:=true").withProperty("enabled:=true").withValue("").setValue("Foo Bar!")&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;- Do a custom action on an object&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Private Function DisplayToString(object)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; MsgBox object.ToString()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;End Function&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Set editCollection = [new editboxCollection](oPage)&amp;nbsp;&amp;nbsp;&amp;nbsp; ' Get all editboxes from a page&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;' Show the toString value of all editboxes that are not visible on a page&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;editCollection.withProperty("visible:=false").each(getRef("DisplayToString"))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Method chaining is very versatile, with the trap of being used to much. Actually it does pretty much the same using the 'with' keyword with objects. It can make your code more clear, or just more obfuscated. Use it wisely.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1708518509752812818-6997294998192257809?l=automated-chaos.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://automated-chaos.blogspot.com/feeds/6997294998192257809/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1708518509752812818&amp;postID=6997294998192257809' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/6997294998192257809'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/6997294998192257809'/><link rel='alternate' type='text/html' href='http://automated-chaos.blogspot.com/2011/12/qtp-and-method-chaining-disclosed.html' title='QTP and Method Chaining disclosed'/><author><name>Bas M. Dam</name><uri>http://www.blogger.com/profile/07594616635957734329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1708518509752812818.post-8074840481406366679</id><published>2011-05-11T19:53:00.000+02:00</published><updated>2011-05-11T19:53:05.179+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='QTP'/><category scheme='http://www.blogger.com/atom/ns#' term='pitfalls'/><category scheme='http://www.blogger.com/atom/ns#' term='coding'/><title type='text'>Curious QTP behaviour when using on error: Proceed to Next Step</title><content type='html'>Because we build our own framework, the on error settings in QTP are default on "Proceed to Next Step" for our unattended continuous script. So when a test is scheduled in the middle of the night, the test won't stall on errors like a function with an argument too few or many, an array that is out of bounds or an accidentally undeclared variable (please build an undeclared variable checker HP, &lt;a href="http://www.patterson-consulting.net/downloads/Default.aspx"&gt;the Patterson boys&lt;/a&gt; could do it years ago, you can do it too!).&lt;br /&gt;&lt;br /&gt;It works fine most of the time, although debugging is done with an "attended run" script and all possible error detection on: Popup Messagebox and Option Explicit everywhere.&lt;br /&gt;&lt;br /&gt;The curious behaviour happened in an Select Case. Consider this code:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Option Explicit &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Dim myCondition : myCondition = 2 &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Select Case myCondition&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; &amp;nbsp; Case 1 MsgBox "Wooh! Condition 1"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; &amp;nbsp; Case 2 MsgBox "Displaying undeclared variable: " &amp;amp; undeclaredVariable&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp; &amp;nbsp; Case 3 MsgBox "Meh, Condition 3"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;End Select&amp;nbsp; &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;When you run this code in attended mode, you'll get a nice error nagging about the undeclared variable.&lt;br /&gt;However, when you run this in unattended mode, you'll get a messagebox with the text: "Meh, condition 3"&lt;br /&gt;&lt;br /&gt;QTP is doing what it says: Continue with the next step. But the step is not fulfilling the Select condition and program technical a major sin!&lt;br /&gt;Because I ran this accidentally in unattended mode, it took me some while to get a finger behind the error. In the end, I learned to always debug in attended mode.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1708518509752812818-8074840481406366679?l=automated-chaos.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://automated-chaos.blogspot.com/feeds/8074840481406366679/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1708518509752812818&amp;postID=8074840481406366679' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/8074840481406366679'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/8074840481406366679'/><link rel='alternate' type='text/html' href='http://automated-chaos.blogspot.com/2011/05/curious-qtp-behaviour-when-using-on.html' title='Curious QTP behaviour when using on error: Proceed to Next Step'/><author><name>Bas M. Dam</name><uri>http://www.blogger.com/profile/07594616635957734329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1708518509752812818.post-5754773461388552217</id><published>2011-05-10T20:40:00.000+02:00</published><updated>2011-05-10T20:40:02.694+02:00</updated><title type='text'>Stuttering Firefox 4; Solved!</title><content type='html'>&lt;span style="font-family: Verdana,sans-serif;"&gt;Haha! I solved my stuttering, stalling and staggering FireFox 4. An annoying problem that let FF halt for a second while scrolling, typing and selecting.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Verdana,sans-serif;"&gt;The solution: just rename or delete the sessionstore.js file (don't worry, FF will create a new one for you) and restart FireFox. Firefox works as a sunshine right now.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: Verdana,sans-serif;"&gt;For OSX users, it is located here: /Users/{username}/Library/Application Support/Firefox/Profiles/{randomkey}.default/sessionstore.js &lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1708518509752812818-5754773461388552217?l=automated-chaos.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://automated-chaos.blogspot.com/feeds/5754773461388552217/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1708518509752812818&amp;postID=5754773461388552217' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/5754773461388552217'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/5754773461388552217'/><link rel='alternate' type='text/html' href='http://automated-chaos.blogspot.com/2011/05/stuttering-firefox-4-solved.html' title='Stuttering Firefox 4; Solved!'/><author><name>Bas M. Dam</name><uri>http://www.blogger.com/profile/07594616635957734329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1708518509752812818.post-1231514987445010806</id><published>2011-05-05T20:09:00.005+02:00</published><updated>2011-05-05T21:28:26.196+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='snel zoeken'/><category scheme='http://www.blogger.com/atom/ns#' term='marktplaats'/><title type='text'>Sneller zoeken op Marktplaats</title><content type='html'>&lt;span style="font-family:verdana;"&gt;Het zoeken naar spulletjes op &lt;a href="http://www.marktplaats.nl/"&gt;marktplaats&lt;/a&gt; kan soms wat tijdrovend zijn. Zo ben ik al een tijdje op zoek naar een bankierslamp die ook wel een notarislamp genoemd wordt. Als eerste zoek je dus op "bankierslamp" en krijg je 10 hits. Na die een beetje doorgelopen te hebben zoek je vervolgens op "notarislamp" met 16 hits. Naast dat er 4 dubbele in de lijst staan, wil je ook nog even terug naar de zoekactie op bankierslamp terwijl je niet zo slim was geweest de notarislamp te zoeken in een aparte tab. Inefficiënte ellende alom.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Booleaanse logica&lt;/span&gt;&lt;br /&gt;Vandaar dat ik wat ben gaan experimenteren met de marktplaats zoek functie (je kan ze ook deels ontdekken via de geavanceerde search, maar dat zit weer 1 klik verder, dus wie komt daar nu?). En ontdekte het volgende:&lt;br /&gt;Marktplaats zoekt standaard met AND. Dit kan je overrulen door OR. Ik had dus moeten zoeken op &lt;a href="http://kopen.marktplaats.nl/search.php?from_searchbox_advanced=1&amp;amp;q=notarislamp+or+bankierslamp"&gt;"bankierslamp or notarislamp"&lt;/a&gt;: 22 hits.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Parenthesiwat?&lt;/span&gt;&lt;br /&gt;Dit kan je ook combineren met een AND criteria, bijvoorbeeld bij het zoeken op skeelers oftewel inline skates. Om deze zoekterm in te voeren zoek ik op "skeelers or inline skates". De AND criteria tussen &lt;span style="font-style: italic;"&gt;inline&lt;/span&gt; en &lt;span style="font-style: italic;"&gt;skates&lt;/span&gt; heb ik hier niet ingetikt, want dat marktplaats standaard. Helaas zoekt marktplaats dan op alle termen waar &lt;span style="font-style: italic;"&gt;skeelers&lt;/span&gt; of &lt;span style="font-style: italic;"&gt;inline&lt;/span&gt; in voorkomt, en daarnaast in elk geval &lt;span style="font-style: italic;"&gt;skates&lt;/span&gt;.&lt;br /&gt;Oplossing: Haakjes! Zoeken op &lt;a href="http://kopen.marktplaats.nl/search.php?from_searchbox_advanced=1&amp;amp;q=skeelers+or+%28inline+skates%29"&gt;"skeelers or (inline skates)"&lt;/a&gt; zorgt ervoor dat marktplaats begrijpt wat je wilt.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Uitgesloten&lt;/span&gt;&lt;br /&gt;Een andere mogelijkheid is uitsluiten met NOT. Zo zocht ik een sleutel om een klok mee op te winden. De zoekterm "sleutel klok" levert resultaten op, maar helaas nog heel veel in combinatie met sloten. Om deze uit te sluiten zoek je op &lt;a href="http://kopen.marktplaats.nl/search.php?from_searchbox_advanced=1&amp;amp;q=sleutel+klok+not+slot"&gt;"sleutel klok not slot"&lt;/a&gt;, et voila.&lt;br /&gt;&lt;br /&gt;Je kan dit natuurlijk net zo ingewikkeld maken als je wilt, mijn huidige zoekterm voor de gewenste lamp ziet er nu als volgt uit:&lt;br /&gt;&lt;a href="http://kopen.marktplaats.nl/search.php?from_searchbox_advanced=1&amp;amp;q=%28%28notaris+or+bankiers%29+and+lamp%29+or+notarislamp+or+bankierslamp"&gt;"((notaris or bankiers) and lamp) or notarislamp or bankierslamp"&lt;/a&gt;, waarbij ik dus ook de anglicismen "notaris lamp" en "bankiers lamp" vind: 31 hits.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;Sterretje en spelling&lt;/span&gt;&lt;br /&gt;Op marktplaats komt lui van alle allooi, ook degene die het niet zo nauw nemen met onze geliefde spelling. Skeelers wil je ook wel eens vinden onder de naam skealers en inline skates als inlijn skeets, skeates, skeats of skaats. Je kan hier een mooie OR term mee bouwen, sneller is het gebruik van het sterretje. &lt;/span&gt;&lt;span style="font-family:verdana;"&gt;Op marktplaats heb ik een wildcard ontdekt en gelijk een hele krachtige: de spin (*) die matcht op alles behalve de spatie.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Om niets te missen van het buitenspeelgebeuren zoek je op &lt;a href="http://kopen.marktplaats.nl/search.php?from_searchbox_advanced=1&amp;amp;q=sk*lers+or+%28inl*n*+sk*t*s%29"&gt;"sk*lers or (inl*n* sk*t*s)"&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Slim&lt;/span&gt;&lt;br /&gt;Gelukkig is marktplaats zelf ook slim. Het heeft een library van veelgebruikte termen. Zoek je dus op skeelers, dan krijg je ook automatisch alle zoektermen voor alle andere vormen van inline skating terug. Helaas zoek je op marktplaats vaak niet altijd op een veelgebruikte term en dan is het wel superhandig als je met een beetje slimme zoekterm snel resultaten kan vinden.&lt;br /&gt;&lt;br /&gt;Mocht je nog meer handige zoektips hebben, dan hoor ik ze graag in de comments!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1708518509752812818-1231514987445010806?l=automated-chaos.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://automated-chaos.blogspot.com/feeds/1231514987445010806/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1708518509752812818&amp;postID=1231514987445010806' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/1231514987445010806'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/1231514987445010806'/><link rel='alternate' type='text/html' href='http://automated-chaos.blogspot.com/2011/05/sneller-zoeken-op-marktplaats.html' title='Sneller zoeken op Marktplaats'/><author><name>Bas M. Dam</name><uri>http://www.blogger.com/profile/07594616635957734329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1708518509752812818.post-6733757510045476751</id><published>2010-12-01T21:59:00.004+01:00</published><updated>2011-05-11T19:53:38.053+02:00</updated><title type='text'>Using the Levenshtein Distance to get the best match from a list</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: verdana;"&gt;A while ago, I created a document in which I explained how to use the Levenshtein Distance to get the best match from a list of options. Well, the article has its own introduction so if you are interested; start reading!&lt;/span&gt;&lt;br /&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: verdana;"&gt;&lt;a href="https://docs.google.com/viewer?a=v&amp;amp;pid=explorer&amp;amp;chrome=true&amp;amp;srcid=0B_3gn-VzG3ekMmE2OTExOWMtODE5YS00NmJiLTgwNjItNTZiY2NlYjEzMDIz&amp;amp;hl=en"&gt;Using the Levenshtein Distance to get the best match from a list (pdf)&lt;/a&gt; &lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1708518509752812818-6733757510045476751?l=automated-chaos.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://automated-chaos.blogspot.com/feeds/6733757510045476751/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1708518509752812818&amp;postID=6733757510045476751' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/6733757510045476751'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/6733757510045476751'/><link rel='alternate' type='text/html' href='http://automated-chaos.blogspot.com/2010/12/using-levenshtein-disctance-to-get-best.html' title='Using the Levenshtein Distance to get the best match from a list'/><author><name>Bas M. Dam</name><uri>http://www.blogger.com/profile/07594616635957734329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1708518509752812818.post-1625513330346531303</id><published>2010-11-19T20:12:00.006+01:00</published><updated>2010-11-19T21:25:50.241+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='QTP'/><category scheme='http://www.blogger.com/atom/ns#' term='QTP10'/><title type='text'>QTP 10 first impressions: Meh</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;This week, QTP 10 was installed at our workspace. We upgraded from 9.1 to 10, so we could also experience all new features of 9.5.&lt;/span&gt;&lt;/span&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;First of all, this is written from my own perspective. I don't use the object repository, the default report, multiple actions or the native QTP connection. I know, these things are improved, but I cannot write about them.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;The good things&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;OK, the function viewer is great. Unfortunately, it does not display classes and properties, while functions and subs inside classes are displayed as Publics. What was the problem with displaying classes as expandable trees and with properties and methods underneath you would think.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;Also functions starting with a square bracket [ are not rendered in the function viewer.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;The Todo list could become quite handy, but after years working without it, I can... do without it.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;The bad things&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;200 Megs. That is the amount of RAM QTP consumes if I start it, even without any scripts loaded. Just to be fair, I think it is more a problem with the installation and that only 2 of the 30(!!) patches are loaded by default, but I cannot change it and it bothers me. So I categorized it as a bad thing.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;This brings me to the next point: &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;Hangs. It hangs a lot and it makes my PC slow, especially Internet Explorer and Windows Explorer. Again, I think it is a problem with the installation and I have to look it up and/or ask support to our godlike and always kind administrators (without them I cannot do anything, so playing nice is important. Maybe they read this.). I think that is a bad thing.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;The "&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;Public Default Property Let Foobar()&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;End Property&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;End Property&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;End Property&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;End Property&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;" syndrom.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;WHY???&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;Variable typing is messed up:&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;Print "123" + "321"&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;results in "123321". Are we switching to Javascript or what? I thought VBScript was proud of their dynamic var typing (as if that is a good thing). Don't mess with my brain by changing the working of the + sign. &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;Make variables dynamic or make operators dynamic, not both!&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;Variable conversion is different:&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;I noticed a classical rounding error: subtracting two numbers can end up with a very small decimal part. Like (not a real example):&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;4.32 + -0.32 results in 4.00000000000014&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;Annoying when you want to compare two numbers during automated testing. &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;The bad things that remain&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;No autocomplete inside libraries.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;No jump-to-function from libraries to other libraries.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;The find is still buggy, with annoying "forward or backward" radiobutton.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;'Sometimes a duplicate code line overwrites other code' bug.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;No declaration check on variables other than during runtime.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;Set myCompositeClass = [new componentA](new componentB)&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt; results in a syntax error while it is theoretical correct.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;Conclusion&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;I think my installation is not correct, so I had a bad week and am a bit prejudiced about my new QTP. The function viewer certainly speeds up my work, unfortunately it is implemented poorly. The problems I have with my memory and performance is probably due to the installation, on my run PCs I do not have these problems, only on my development machine (but why couldn't it be correct the first time?). The changed variable conversion and operator functionality is really not a good thing. Besides that it influences our existing tests, it is not an improvement. The remaining annoyances stays, and from a user perspective this is merely a QTP 9.6 release and not a 10 major version. I think it is time HP/Mercury will get a real competitor and we get a real choice what automated test software we can use. They are now functioning like our dutch railway system: "Use our system or don't; we don't bother".&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1708518509752812818-1625513330346531303?l=automated-chaos.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://automated-chaos.blogspot.com/feeds/1625513330346531303/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1708518509752812818&amp;postID=1625513330346531303' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/1625513330346531303'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/1625513330346531303'/><link rel='alternate' type='text/html' href='http://automated-chaos.blogspot.com/2010/11/qtp-10-first-impressions-meh.html' title='QTP 10 first impressions: Meh'/><author><name>Bas M. Dam</name><uri>http://www.blogger.com/profile/07594616635957734329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1708518509752812818.post-3876935757034761808</id><published>2010-11-18T12:56:00.003+01:00</published><updated>2010-11-18T12:58:44.156+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tricks'/><category scheme='http://www.blogger.com/atom/ns#' term='VBScript'/><category scheme='http://www.blogger.com/atom/ns#' term='QTP'/><category scheme='http://www.blogger.com/atom/ns#' term='classes'/><category scheme='http://www.blogger.com/atom/ns#' term='coding'/><title type='text'>QTP and how to create an autodestruct class</title><content type='html'>&lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px Verdana"&gt;&lt;span class="Apple-style-span"  style=" ;font-size:10.8333px;"&gt;Somewhere in our application under test, we have a webpage that only continues loading if the mouse is slightly moved. The page is loading while QTP is syncing the page. During the syncing, I cannot send mouse move commands from QTP to the application. &lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px Verdana"&gt;&lt;span style="letter-spacing: 0.0px"&gt;I don’t know why the application has this feature and “they” don’t want to fix it, so… work around time.&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px Verdana; min-height: 13.0px"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px Verdana"&gt;&lt;span style="letter-spacing: 0.0px"&gt;I created a low profile mousemove application in C that only does one thing: After 5 seconds it moves the mouse cursor one pixel to the right. And after 5 seconds it moves the cursor one pixel to the left. Repeat.&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px Verdana; min-height: 13.0px"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px Verdana"&gt;&lt;span style="letter-spacing: 0.0px"&gt;Actually it is an cut down version of out nolock.exe application, this application sniffs the mouse cursor movements. If it detects inactivity for 10 minutes, it moves the mouse cursor slightly in the same manner as discussed above. This program has a shortcut in the Windows Startup folder and prevent the screen from locking when automated tests are running.&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px Verdana; min-height: 13.0px"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px Verdana"&gt;&lt;span style="letter-spacing: 0.0px"&gt;But back to the autodestruct class. We want to have a “single line of code” to implement this in any function where we expect the screen to hang.  This class starts the mouse moving as soon as it is created and stops the mouse moving when it is destroyed.&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px Verdana; min-height: 13.0px"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;Private Const MOUSE_MOVE_APPL_NAME = “mouseMover.exe”&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;Private Const BINARIES_FOLDER = “C:\QTP_Framework\tooling\bin\”&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'; min-height: 12.0px"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;Class cls_AutoDestructMouseMover&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;Private Sub class_initialize()&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt;  &lt;/span&gt;‘ Put the cursor somewhere to prevent it is on the extreme right position&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt;  &lt;/span&gt;call extern.SetCursorPos(100, 150)&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt;  &lt;/span&gt;‘ Run the external mouse move application&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt;  &lt;/span&gt;systemutil.Run BINARIES_FOLDER &amp;amp; _&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 108.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;MOUSE_MOVE_APPL_NAME, "", BINARIES_FOLDER&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;End Sub&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'; min-height: 12.0px"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;Private sub class_terminate()&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt;  &lt;/span&gt;‘ Kill the mouse move application&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt;  &lt;/span&gt;systemUtil.CloseProcessByName MOUSE_MOVE_APPL_NAME&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;End Sub&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;End Class&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px Verdana; min-height: 13.0px"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px Verdana"&gt;&lt;span style="letter-spacing: 0.0px"&gt;And make a public accessor for the class:&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px Verdana; min-height: 13.0px"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;Public function [new AutoDestructMouseMover]&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;Set [new AutoDestructMouseMover] = new cls_AutoDestructMouseMover&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;End Function&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px Verdana; min-height: 13.0px"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px Verdana"&gt;&lt;span style="letter-spacing: 0.0px"&gt;Now, we can implement the class whenever it is needed:&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px Verdana; min-height: 13.0px"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;Public Function Example&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;‘ Create the object, make it move!&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;Dim autoDestructMouseMover : Set autoDestructMouseMover = [new AutoDestructMouseMover]&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'; min-height: 12.0px"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;Call TimeConsumingFunction&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'; min-height: 12.0px"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;‘ Destroy the object, let it stop!&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;Set autoDestructMouseMover = Nothing&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;End Function&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px Verdana; min-height: 13.0px"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px Verdana"&gt;&lt;span style="letter-spacing: 0.0px"&gt;But wait, we called it an “autodestruct” class, what about the autodestruct? Well, The last line of code is not necessary. When the Example function ends, it automatically destroys all variables and objectpointers with local scope. We can simply reduce the implementation of the autodestructor to one line of code (I know, I am cheating with the semicolon):&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px Verdana; min-height: 13.0px"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;Public Function Example&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;‘ Create the object, make it move!&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;Dim autoDestructMouseMover : Set autoDestructMouseMover = [new AutoDestructMouseMover]&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'; min-height: 12.0px"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;Call TimeConsumingFunction&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;End Function&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px Verdana; min-height: 13.0px"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px Verdana"&gt;&lt;span style="letter-spacing: 0.0px"&gt;And the autoDestructMouseMover object is automatically destroyed with the function clean up.&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px Verdana; min-height: 13.0px"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px Verdana"&gt;&lt;span style="letter-spacing: 0.0px"&gt;Nice. But are there more appliances for an autodestruct object? Oh, yes. &lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px Verdana"&gt;&lt;span style="letter-spacing: 0.0px"&gt;What do you think an autoDestructStackTracer?&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;Class cls_AutoDestructStackTracer&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;Private procedureName_&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;Public Sub Init(pName)&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 36.0px; text-indent: 36.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;procedureName_ = pName&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 36.0px; text-indent: 36.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;Print now &amp;amp; “ ADST Start “ &amp;amp; procedureName_&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;End Sub&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'; min-height: 12.0px"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;Private sub class_terminate()&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt;  &lt;/span&gt;Print now &amp;amp; “ ADST Exit “ &amp;amp; procedureName_&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;End Sub&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;End Class&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px Verdana; min-height: 13.0px"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px Verdana"&gt;&lt;span style="letter-spacing: 0.0px"&gt;And make a public accessor for the class:&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px Verdana; min-height: 13.0px"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;Public function [new AutoDestructStackTracer](pName)&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;Set [new AutoDestructStackTracer] = new cls_AutoDestructStackTracer&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;[new AutoDestructStackTracer].Init pName&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;End Function&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px Verdana; min-height: 13.0px"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px Verdana"&gt;&lt;span style="letter-spacing: 0.0px"&gt;And let’s test it:&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px Verdana; min-height: 13.0px"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;Public Function ExampleParent&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;Dim autoDestructStackTracer : Set autoDestructStackTracer = [new AutoDestructStackTracer](“ExampleParent”)&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;Print “I’m with ExampleParent now!”&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;Call ExampleChild&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;End Function&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'; min-height: 12.0px"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;Public Function ExampleChild&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;Dim autoDestructStackTracer : Set autoDestructStackTracer = [new AutoDestructStackTracer](“ExampleChild”)&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;Print “I’m with ExampleChild now!”&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;End Function&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'; min-height: 12.0px"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;Call ExampleParent&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;Output:&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;18-11-2010 9:06:06 ADST Start ExampleParent&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;I’m with ExampleParent now!&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;18-11-2010 9:06:06 ADST Start ExampleChild&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;I’m with ExampleChild now!&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;18-11-2010 9:06:06 ADST Exit ExampleChild&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px 'Courier New'"&gt;&lt;span style="letter-spacing: 0.0px"&gt;18-11-2010 9:06:06 ADST Exit ExampleParent&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px Verdana; min-height: 13.0px"&gt;&lt;span style="letter-spacing: 0.0px"&gt;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; line-height: 13.0px; font: 11.0px Verdana"&gt;&lt;span style="letter-spacing: 0.0px"&gt;And consider uses of an &lt;/span&gt;&lt;span style="font: 11.0px 'Courier New'; letter-spacing: 0.0px"&gt;[new AutoDestructFunctionTimer](pName)&lt;/span&gt;&lt;span style="letter-spacing: 0.0px"&gt; to measure the performance of your different functions. Or a [&lt;/span&gt;&lt;span style="font: 11.0px 'Courier New'; letter-spacing: 0.0px"&gt;new ScreenShotOnFunctionExit]&lt;/span&gt;&lt;span style="letter-spacing: 0.0px"&gt;  (and more generalized: &lt;/span&gt;&lt;span style="font: 11.0px 'Courier New'; letter-spacing: 0.0px"&gt;[new ExecuteOnFunctionExit](“call PerformScreenshot”))&lt;/span&gt;&lt;span style="letter-spacing: 0.0px"&gt; when you have lots of functions with multiple exit points.&lt;/span&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1708518509752812818-3876935757034761808?l=automated-chaos.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://automated-chaos.blogspot.com/feeds/3876935757034761808/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1708518509752812818&amp;postID=3876935757034761808' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/3876935757034761808'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/3876935757034761808'/><link rel='alternate' type='text/html' href='http://automated-chaos.blogspot.com/2010/11/qtp-and-how-to-create-autodestruct_18.html' title='QTP and how to create an autodestruct class'/><author><name>Bas M. Dam</name><uri>http://www.blogger.com/profile/07594616635957734329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1708518509752812818.post-3872868759344464380</id><published>2009-10-29T09:29:00.007+01:00</published><updated>2009-10-29T09:50:28.495+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='QTP'/><category scheme='http://www.blogger.com/atom/ns#' term='book review'/><title type='text'>Book review Quicktest Professional Unplugged</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_k--5h5XK9eM/SulVsTHkVDI/AAAAAAAAAFw/LDiU1-YPsDM/s1600-h/quicktestprofessional_frontcover+copy.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 100px; height: 130px;" src="http://1.bp.blogspot.com/_k--5h5XK9eM/SulVsTHkVDI/AAAAAAAAAFw/LDiU1-YPsDM/s200/quicktestprofessional_frontcover+copy.png" alt="" id="BLOGGER_PHOTO_ID_5397939847914869810" border="0" /&gt;&lt;/a&gt;&lt;span style="font-weight: bold;font-family:verdana;" &gt;Introduction&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;After unpacking the book, it smiled to me in a pretty color setting, although, it reminded me on my times working at &lt;a href="http://www.abnamro.com/about/shield-colours.cfm"&gt;ABN AMRO&lt;/a&gt;. The cover shows the well known picture of the QTP splash window. The book is quite large, approximately 20x30cm and contains around 430 pages.&lt;/span&gt; &lt;span style="font-family:verdana;"&gt;The pages are all printed in black and white (well, the white was not printed, it was more the property of the paper itself). It is build up into chapters, and the book does have a table of contents and an index.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:verdana;" &gt;Content&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;The first thing that you’ll notice is lots of sample code. This comes in two ways: Code that supports the text and code that belongs to the challenges at the end of each chapter. &lt;/span&gt; &lt;span style="font-family:verdana;"&gt;The book is mainly written in a the first person plural form, so you will never be addressed personally, making the book somewhat formal. Nevertheless, it is an easy read. The layout is open and organized.&lt;/span&gt; &lt;span style="font-family:verdana;"&gt;Each chapter handles one subject and is providing you an introduction to this subject justifying why it is included in the book. Then it hops directly to the matter. At the end of each chapter is room for your own notes.&lt;/span&gt;  &lt;span style="font-family:verdana;"&gt;&lt;br /&gt;&lt;br /&gt;Most of the subjects are not new, and can be found over the web, the QTP help file and documentation provided by Mercury/HP, but it is very helpful to have it packed in one complete book and only the –no need to search anymore- property makes it worthwhile owning this book alone.&lt;/span&gt; &lt;span style="font-family:verdana;"&gt;When I have to cover a new subject during my daily work, I peek into the applicable chapter which brings me on track in no time. &lt;/span&gt;  &lt;span style="font-family:verdana;"&gt;The text and the code sticks very to the matter, meaning it is all about solving low level problems you’ll encounter by coding your automated tests.&lt;br /&gt;&lt;br /&gt;It does not describe test methodologies or how to build a test framework. Well, actually there is a chapter “Designing Frameworks”,  but it is more a guideline and best practices enumeration. Also you’ll not find examples dealing the problems of a virtual donut shop or remote control. &lt;/span&gt;  &lt;span style="font-family:verdana;"&gt;Tarun Lalwani writes: “This book is targeted at automation engineers who want to exploit the power that QTP offers…” and I think that is a very good description of the book. The sample code is of high level, sometimes too extensive. Programming experience is necessary to extract the full potential of it.&lt;/span&gt;  &lt;span style="font-weight: bold;font-family:verdana;" &gt;&lt;br /&gt;&lt;br /&gt;Conclusion&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;QuickTest Professional Unplugged is a very comprehensive book written by experience. It is full of handy sample code and neat tricks. Each chapter will provide you with one or more “I didn’t know that!” experiences. The book is created for a small audience, but for this particular audience it is certainly a must have.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1708518509752812818-3872868759344464380?l=automated-chaos.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://automated-chaos.blogspot.com/feeds/3872868759344464380/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1708518509752812818&amp;postID=3872868759344464380' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/3872868759344464380'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/3872868759344464380'/><link rel='alternate' type='text/html' href='http://automated-chaos.blogspot.com/2009/10/book-review-quicktest-professional.html' title='Book review Quicktest Professional Unplugged'/><author><name>Bas M. Dam</name><uri>http://www.blogger.com/profile/07594616635957734329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_k--5h5XK9eM/SulVsTHkVDI/AAAAAAAAAFw/LDiU1-YPsDM/s72-c/quicktestprofessional_frontcover+copy.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1708518509752812818.post-2613894344619293808</id><published>2009-04-26T15:19:00.010+02:00</published><updated>2009-07-08T19:32:11.550+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tricks'/><category scheme='http://www.blogger.com/atom/ns#' term='VBScript'/><category scheme='http://www.blogger.com/atom/ns#' term='QTP'/><category scheme='http://www.blogger.com/atom/ns#' term='classes'/><category scheme='http://www.blogger.com/atom/ns#' term='coding'/><title type='text'>How to use classes in QTP revisited</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_k--5h5XK9eM/SfSfwlTK6ZI/AAAAAAAAAFg/jd0VA44GT8c/s1600-h/c64+oog.png"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 100px; height: 100px;" src="http://3.bp.blogspot.com/_k--5h5XK9eM/SfSfwlTK6ZI/AAAAAAAAAFg/jd0VA44GT8c/s200/c64+oog.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5329059916081195410" /&gt;&lt;/a&gt;Classes in QTP are a bit tricky if you want to use them for the first time. You have to know and understand the principle that a class got local scope for the QTP Function Library (.qfl file) it is in, and that if you want to use it in another library, you’ll have to create a constructor (I have shown this before, but I’ll do it again):&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);font-family:courier new;" &gt;' Constructor:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Public Function [new CustomClass]()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;        Set [new CustomClass] = new cls_CustomClass&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;End Function &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);font-family:courier new;" &gt;' Class definition:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Class cls_CustomClass&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;     Private Sub Class_Initialize()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;          Print "Custom Class: I am created!"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;     End Sub&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt; End Class&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);font-family:courier new;" &gt;' using the object in another library:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Dim myClass&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Set myClass = [new CustomClass]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This seems like a drawback, but it creates a great possibility. Normally, it is not possible to pass initialisation parameters into a new class, because Class_Initialize does not accept parameters. But using the constructor function, we can!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Option Explicit&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);font-family:courier new;" &gt;' Make a private variable that we can pass into the class&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Private PARAMETER_ARRAY&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);font-family:courier new;" &gt;' Create a function that returns the requested class. Accepts&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);font-family:courier new;" &gt;' a parameter array. Note: Do not use paramArray, it is reserved!&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Public Function [new customClass](ByVal parameterArray)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;     PARAMETER_ARRAY = parameterArray&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;    &lt;span style="color: rgb(0, 153, 0);"&gt;' Return a clsCustomClass object&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;     Set [new CustomClass] = new cls_CustomClass&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;End Function&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);font-family:courier new;" &gt;' Create the custom class. Classes are always declared Private in QTP&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Class cls_CustomClass&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;     &lt;span style="color: rgb(0, 153, 0);"&gt;' The sub Class_Initialize is used to initialize the object with the&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);font-family:courier new;" &gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;     ' parameters passed into the constructor&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;     Private Sub Class_Initialize()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;          &lt;span style="color: rgb(0, 153, 0);"&gt;' Do something with the parameters&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;         Print join(PARAMETER_ARRAY, vbNewLine)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;     End Sub&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;End Class&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);font-family:courier new;" &gt;' Test code&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Dim myClass&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Set myClass = [new customClass](array("first parameter", "second parameter", "etc."))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Notice what we just did: We created a Private variable, that can only be used by CustomClass classes. So with the use of Private variables with local scope to the library where you put the class in, you create a static variable for the class!&lt;br /&gt;A static variable in this context is a variable that keeps its value and can be used over multiple objects of the same class:&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);font-family:courier new;" &gt;' Declaring the static variables&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Private INSTANCE_COUNTER : INSTANCE_COUNTER = 0&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);font-family:courier new;" &gt;' Constructor:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Public Function [new CustomClass]()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;     Set [new CustomClass] = new cls_CustomClass&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;End Function &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);font-family:courier new;" &gt;' Class definition:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Class cls_CustomClass&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;     Private Sub Class_Initialize()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;          Print "I am created and I have " &amp;amp; INSTANCE_COUNTER &amp;amp; " sister(s)."&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;        INSTANCE_COUNTER = INSTANCE_COUNTER + 1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;     End Sub&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;     Private Sub Class_Terminate()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;          INSTANCE_COUNTER = INSTANCE_COUNTER – 1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;     End Sub&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt; End Class&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);font-family:courier new;" &gt;' using the object in another library:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Dim a, b, c&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Set a = [new CustomClass]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Set b = [new CustomClass]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Set c = [new CustomClass]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Results in:&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;I am created and I have 0 sister(s).&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;I am created and I have 1 sister(s).&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;I am created and I have 2 sister(s).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;By using the static variable as a reference for the object itself, we can create a singleton object. A singleton is an object whereof only one instance at a time can exist. In object oriented languages, singletons are normally used for large objects, or objects that will go bad if multiple instances exists like deadlocks or instability.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Option explicit&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Private SINGLETON : Set SINGLETON = Nothing&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Public function [new Singleton]()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;     If SINGLETON Is Nothing Then&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;          set SINGLETON = new cls_Singleton&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;     End If&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;     Set [new Singleton] = SINGLETON&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;End Function&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Class cls_Singleton&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;     Private Sub Class_Initialize&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;          Print "I am unique!"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;     End Sub&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;End Class&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Dim st1, st2, st3&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Set st1 = [new Singleton]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Set st2 = [new Singleton]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Set st3 = [new Singleton]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Results in only one:&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153);font-family:courier new;" &gt;I am unique!&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;There is a drawback: Once a singleton object is created this way, it is not possible to destroy it without the use of some code violating the object oriented principle.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1708518509752812818-2613894344619293808?l=automated-chaos.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://automated-chaos.blogspot.com/feeds/2613894344619293808/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1708518509752812818&amp;postID=2613894344619293808' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/2613894344619293808'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/2613894344619293808'/><link rel='alternate' type='text/html' href='http://automated-chaos.blogspot.com/2009/04/how-to-use-classes-in-qtp-revisited.html' title='How to use classes in QTP revisited'/><author><name>Bas M. Dam</name><uri>http://www.blogger.com/profile/07594616635957734329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_k--5h5XK9eM/SfSfwlTK6ZI/AAAAAAAAAFg/jd0VA44GT8c/s72-c/c64+oog.png' height='72' width='72'/><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1708518509752812818.post-8144079276135603966</id><published>2009-04-24T22:58:00.011+02:00</published><updated>2009-04-26T20:12:35.759+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='QTP'/><category scheme='http://www.blogger.com/atom/ns#' term='coding'/><title type='text'>QTP variable name conventions</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_k--5h5XK9eM/SfSkBsvf9XI/AAAAAAAAAFo/IjSi2KkDWGY/s1600-h/girlanddog.png"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 100px; height: 100px;" src="http://4.bp.blogspot.com/_k--5h5XK9eM/SfSkBsvf9XI/AAAAAAAAAFo/IjSi2KkDWGY/s200/girlanddog.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5329064608183350642" /&gt;&lt;/a&gt;When you start with a new test automation project, your code is conveniently arranged and you still have a clear overview over the locations and naming of variables and functions. But later on it will become a disaster if you don’t manage it a little bit.&lt;br /&gt;That is why I wrote a name convention article. It is not an official how-you-should-do-it document, it is just the way I do things and written from experience.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);font-family:courier new;" &gt;' Public and Private constants in capitals&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Public Const MOUSEEVENTTF _MOVE = 1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Private Const APPLICATION_MAIN_WINDOW = "name:=My Application"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);font-family:courier new;" &gt;' Functions, Subs and local variables in lowerCamelCase&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Public Function myCustomFunction(thisVariable, thatVariable)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;     &lt;span style="color: rgb(0, 153, 0);"&gt;' Variables with a known type can be declared with the type abbreviation in front of it&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;    Dim arrStaticArry(5), objFile, intCounter, blnReadOnly&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;     &lt;span style="color: rgb(0, 153, 0);"&gt;' Variables with a unknown type are declared without a type abbreviation, This is also applicable for variables used in self commentary code.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;     Dim customContainer, fileWasFound&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;     &lt;span style="color: rgb(0, 153, 0);"&gt;' Consts with local scope are declared with the same format as variables&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;     Const cannotBeChanged = True&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;End Function&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);font-family:courier new;" &gt;' Classes in UpperCamelCase. In QTP I use the cls_ tag in front of it for reasons explained later.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Class cls_EventListener&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;    &lt;span style="color: rgb(0, 153, 0);"&gt;' Public variables are in UpperCamelCase too&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;    Public BufferLength&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;    &lt;span style="color: rgb(0, 153, 0);"&gt;' Private variables with class scope are lowerCamelCase with an underscore behind it&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;     Private updateCounter_, eventNumber_&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;    &lt;span style="color: rgb(0, 153, 0);"&gt;' Properties, Subs and Functions (public and private) are all in UpperCamelCase&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;     Public Property Get EventNumber()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;          EventNumber = eventNumber_&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;     End Property&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;End Class&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In QTP, a class gets a local scope. To make it global, you have to add a function returning that class. As a side effect, this gives you the opportunity to initialize the class. Of course you have to add an init method to your class if you do it this way.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Public Function [new EventListener](initializationParameters)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;     Set [new EventListener] = new cls_EventListener&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;     [new EventListener].Init(initializationParameters)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;End Function&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Now, you can set a new class with the following code in another library:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Set EventListener = [new EventListener]("codebase:=Unicode")&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Side note: The square brackets around a variable lets you enter every character for a variable, including spaces, special characters etc. If you find that inconvenient, you can use an underscore: new_EventListener to mimic normal VB functionality.&lt;br /&gt;I use the square brackets when I want to express importance for example:&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);font-family:courier new;" &gt;' Call the main routine of this script:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;[___ !MAIN! ___]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);font-family:courier new;" &gt;' Or to enjoy my co workers (and to see if they ever peer review my code):&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Dim [  O\-&lt;&gt;-/O  ], [  ¿Que?  ]&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1708518509752812818-8144079276135603966?l=automated-chaos.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://automated-chaos.blogspot.com/feeds/8144079276135603966/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1708518509752812818&amp;postID=8144079276135603966' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/8144079276135603966'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/8144079276135603966'/><link rel='alternate' type='text/html' href='http://automated-chaos.blogspot.com/2009/04/qtp-variable-name-conventions.html' title='QTP variable name conventions'/><author><name>Bas M. Dam</name><uri>http://www.blogger.com/profile/07594616635957734329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_k--5h5XK9eM/SfSkBsvf9XI/AAAAAAAAAFo/IjSi2KkDWGY/s72-c/girlanddog.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1708518509752812818.post-3075434321755674150</id><published>2009-04-08T19:06:00.006+02:00</published><updated>2009-04-08T19:53:16.378+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tricks'/><category scheme='http://www.blogger.com/atom/ns#' term='VBScript'/><category scheme='http://www.blogger.com/atom/ns#' term='QTP'/><category scheme='http://www.blogger.com/atom/ns#' term='arrays'/><title type='text'>A few ways to use arrays</title><content type='html'>&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:verdana;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_k--5h5XK9eM/SdzjTdEL3KI/AAAAAAAAAFY/T7mrgtgZ-XM/s1600-h/gridder.gif"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 100px; height: 100px;" src="http://3.bp.blogspot.com/_k--5h5XK9eM/SdzjTdEL3KI/AAAAAAAAAFY/T7mrgtgZ-XM/s200/gridder.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5322378783004286114" /&gt;&lt;/a&gt;When you first encounter Arrays in QTP it is not very easy to understand quickly. VBScript makes use of a few types of arrays: Static, Dynamic, Assigned to a normal variable and Dictionary objects (the dictionary object is not discussed in this article.). Static and Dynamic arrays can be one dimensional or multidimensional.&lt;br /&gt;&lt;br /&gt;First the simple static array. Static because it can only contain a fixed amount of items; Simple because we only put strings in it referred by the indexnumber (or subscript) of the array:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;' Simple static array&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Dim weekdays(6)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;weekdays(0) = "Mon"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;weekdays(1) = "Tue"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;weekdays(2) = "Wed"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;weekdays(3) = "Thu"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;weekdays(4) = "Fri"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;weekdays(5) = "Sat"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;weekdays(6) = "Sun"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;When you don't have plans to use the subscript, you can also create the array directly. And yes, it works the same with index numbers as with the weekdays array, but it is good programming practice to use the former method if you want to call the array items by subscript number.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;' Simple assigned array&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Dim workdays&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;workdays = array("Mon", "Wed", "Thu", "Fri")&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;As you can see, the variable does not have to be declared as an array, so theoretically every variable can be set as an array just as every variable can be set as an object. Although, with arrays you don't need the set statement.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Sometimes it is more convenient to dynamically increase and decrease the array size. Then you have to create a dynamic array. This is an array declared the same way as in the simple static array, but without the number of elements, just empty parenthesis: dim myArray()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;To set the amount of array items, you have to use ReDim like ReDim myArray(n) where n is the amount of items you want to use +1 (The first subscript is always 0). Other then in a static array declaration (like Dim myArray(5)), the number of subscripts in a ReDim statement can be a variable or constant.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Whenever you use ReDim, the array is reïnitialized, except when you use the Preserve command, indicating you want to reuse the already set values:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;' Simple dynamic assigment of an array&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Dim myPets()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;ReDim myPets(2)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;myPets(0) = "Dog"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;myPets(1) = "Cat"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;myPets(2) = "Hippopotamus"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;ReDim Preserve myPets(3)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;myPets(3) = "Rabbit"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;msgbox "My pets: " &amp;amp; join(myPets, ", ")&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;The join(array[, separation character(s)]) function lets you easily merge an array to a string.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Another trick is to use join to make an html table easily:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;newTableRow = "" &amp;amp; join(arrElements, "") &amp;amp; ""&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:verdana;" &gt;Multidimensional arrays&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;A multidimensional array is used to store data or objects in a matrix. You can create virtually create as much dimensions if you want (not really unlimited of course, but keep in mind this good rule with programming: If you have to ask what the limit is for some kind of instance, probably there is something wrong with your design)&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;' Multidimensional static array, the next code is pure and alone for demonstration purposes&lt;br /&gt;' it is not optimised, maybe even not correct and there are better ways to achieve this&lt;br /&gt;Dim bcCalendar(2100, 12, 31)&lt;br /&gt;Dim dayCounter, maxDay, cYear, cMonth, cDay&lt;br /&gt;dayCounter = 6&lt;br /&gt; &lt;br /&gt;For cYear = 0 to 2100&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;For cMonth = 1 to 12&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Select Case cMonth&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Case 1,3,5,7,8,10,12&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;maxDay = 31&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Case 4,6,9,11&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;maxDay = 30&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Case 2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;maxDay = 28 + abs((cYear mod 400 = 0) or ((cYear mod 4 = 0) and not (cYear mod 100 = 0)))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;End Select&lt;br /&gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;For cDay = 1 to maxDay&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bcCalendar(cYear, cMonth, cDay) = weekday((dayCounter mod 7)+1)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dayCounter = dayCounter + 1&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Next&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Next&lt;br /&gt;Next&lt;br /&gt; &lt;br /&gt;msgbox "Charles Darwin was born on a " &amp; WeekdayName(bcCalendar(1809, 2, 12))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:verdana;" &gt;Passing arrays&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Arrays are passed the same way as variables are:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Default: By Reference&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;With ByRef in the function declaration: By Reference&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;With ByVal in the function declaration: By Value&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;With parenthesis around the argument in the function call: always By Value (ByRef in the function declaration is omitted)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:verdana;" &gt;Arrays filled with objects&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Arrays do not only have to contain variables, they can also contain objects, which is great to make a collection of QTP gui objects, dictionaries, but also class objects to create child classes under a parent.&lt;br /&gt;Arrays can even contain other arrays. This is useful if you want to create a fully dynamic multidimensional array. (Normally, in a multidimensional array, only the last item is expandable with a redim preserve statement.)&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1708518509752812818-3075434321755674150?l=automated-chaos.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://automated-chaos.blogspot.com/feeds/3075434321755674150/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1708518509752812818&amp;postID=3075434321755674150' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/3075434321755674150'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/3075434321755674150'/><link rel='alternate' type='text/html' href='http://automated-chaos.blogspot.com/2009/04/few-ways-to-use-arrays.html' title='A few ways to use arrays'/><author><name>Bas M. Dam</name><uri>http://www.blogger.com/profile/07594616635957734329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_k--5h5XK9eM/SdzjTdEL3KI/AAAAAAAAAFY/T7mrgtgZ-XM/s72-c/gridder.gif' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1708518509752812818.post-3055549571592671508</id><published>2008-12-10T19:03:00.002+01:00</published><updated>2008-12-10T19:08:43.464+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tricks'/><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='QTP'/><title type='text'>Performance increase in table lookup functions</title><content type='html'>&lt;span style="font-family: verdana;"&gt;Using object properties instead of QTP standard functions will improve the performance of QTP tests significantly. In our case, we often want to lookup the location of a certain value in a WebTable. QTP provides several functions to read out data from a table, but is slow when used iterating the table (like two for loops, one iterating the rows, the embedded second one iterating the columns per row).&lt;/span&gt;&lt;br /&gt; &lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Example of a conservative way to do this:&lt;/span&gt;&lt;br /&gt; &lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Public Function LocateTextInTable(byRef tbl, textToFind, byRef row, byRef col)&lt;/span&gt;&lt;br /&gt; &lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;For row = 1 to tbl.RowCount&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;For col = 1 to tbl.ColCount&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;If tbl.GetCellData(row, col) = textToFind then&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;LocateTextInTable = True&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Exit function   &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;End if&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Next&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Next&lt;/span&gt;&lt;br /&gt;        &lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;row = -1 : col = -1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;LocateTextInTable = False&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;End Function&lt;/span&gt;&lt;br /&gt; &lt;br /&gt;&lt;span style="font-family: verdana;"&gt;The crux is this: .GetCellData is not a very fast method and with a table, consisting of 30 rows and 10 columns, this method is iterated up to 300 times in the most worse case scenario (= text not found).&lt;/span&gt;&lt;br /&gt; &lt;br /&gt;&lt;span style="font-family: verdana;"&gt;A faster way to retrieve the data is through the Document Object Model (DOM). This allows you to use the more native properties of an object with the sacrifice of some ease of use.&lt;/span&gt;&lt;br /&gt; &lt;br /&gt;&lt;span style="font-family: verdana;"&gt;A table consists of row elements and each row element contains one or more cells. We can iterate them just the same way as we did with the function above:&lt;/span&gt;&lt;br /&gt; &lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Public Function LocateTextInTableDOM(byRef tbl, textToFind, byRef row, byRef col)&lt;/span&gt;&lt;br /&gt; &lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Dim objRow, objCell&lt;/span&gt;&lt;br /&gt; &lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;row = 1 : col = 1&lt;/span&gt;&lt;br /&gt; &lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;For each objRow in tbl.object.Rows&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;For each objCol in objRow.Cells&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;If objCol.Value = textToFind then&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;LocateTextInTableDOM = True&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Exit function   &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;End if&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;col = col + 1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Next&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;row = row + 1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Next&lt;/span&gt;&lt;br /&gt; &lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;row = -1 : col = -1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;LocateTextInTableDOM = False&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;End Function&lt;/span&gt;&lt;br /&gt; &lt;br /&gt;&lt;span style="font-family: verdana;"&gt;From our experience, this will increase the performance of the function with a factor 10.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;But be aware, there is one big assumption: This function assumes that the row objects (and cell objects) are perfectly iterated from the first row to the last row and in this exact order. Although a For…Each construct cannot guarantee this behaviour, we never encountered an incorrect location.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1708518509752812818-3055549571592671508?l=automated-chaos.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://automated-chaos.blogspot.com/feeds/3055549571592671508/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1708518509752812818&amp;postID=3055549571592671508' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/3055549571592671508'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/3055549571592671508'/><link rel='alternate' type='text/html' href='http://automated-chaos.blogspot.com/2008/12/performance-increase-in-table-lookup.html' title='Performance increase in table lookup functions'/><author><name>Bas M. Dam</name><uri>http://www.blogger.com/profile/07594616635957734329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1708518509752812818.post-3236917599836475460</id><published>2008-11-04T19:22:00.006+01:00</published><updated>2008-11-04T19:54:27.015+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='function pointer'/><category scheme='http://www.blogger.com/atom/ns#' term='VBScript'/><category scheme='http://www.blogger.com/atom/ns#' term='QTP'/><category scheme='http://www.blogger.com/atom/ns#' term='keywords'/><title type='text'>How to make use of Function Pointers in a Keyword Driven Approach</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_k--5h5XK9eM/SRCaSAcQ_ZI/AAAAAAAAAE4/HAhDr-NnwVg/s1600-h/SuperBasic.png"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 96px; height: 96px;" src="http://3.bp.blogspot.com/_k--5h5XK9eM/SRCaSAcQ_ZI/AAAAAAAAAE4/HAhDr-NnwVg/s200/SuperBasic.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5264877598542986642" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style=";font-family:verdana;font-size:85%;"  &gt;A commonly used automated test methodology is working with user defined keywords. The tester defines the keyword with parameters next to it and the automated testtool processes this keyword and executes the corresponding function.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:verdana;font-size:85%;"  &gt;There are two ways I know of to make this work in QTP, both with advantages and drawbacks.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:verdana;font-size:85%;"  &gt;A "select case" construction gives you flexibility, but with every keyword you have to add a case manually.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Select Case KeyWord&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;        Case "login"            call login()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;        Case "enter user"       call enterUser()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;        Case Else               msgbox "Invalid Keyword: '" &amp;amp; KeyWord &amp;amp; "'"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;End Select&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Using an eval or execute can lead to type mismatch errors. You can circumvent this by putting in an "On error resume next", but this will lead to no error handling at all by the VBScript engine. Any undefined variable normally results in a "Variable is undefined" error, which can be a great help. You are losing that with an "on error resume next" statement.&lt;br /&gt;Also, a execute or eval does not return a value or object, unless you are capturing that with a variable in the string of the execute itself.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;On error resume next&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Execute ("TestResult = " &amp;amp; KeyWord &amp;amp; "()")      ' -&gt; Any error within the processing of the KeyWord will not be trapped.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;On error goto 0&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In this post, I will show you another way to dynamically assign keywords to functions in a fast way, with trapping of invalid keywords on a soft way (programmatically and not by the VBScript engine), and keeping the normal error behaviour. This can be done by creating a function pointer to the function and verifying if the function pointer is valid. If so, it can be executed as if it is a normal function:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        Dim fp&lt;br /&gt;&lt;br /&gt;        On error resume next&lt;br /&gt;        Set fp = GetRef(KeyWord)&lt;br /&gt;        On error goto 0&lt;br /&gt;&lt;br /&gt;        If IsObject(fp) then&lt;br /&gt;        &amp;nbsp;&amp;nbsp;        TestResult = fp&lt;br /&gt;        Else&lt;br /&gt;        &amp;nbsp;&amp;nbsp;        MsgBox "Keyword '" &amp;amp; KeyWord &amp;amp; "' could NOT be mapped to a valid function."&lt;br /&gt;        End if&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;A function pointer can be used just as a normal function. A drawback of VBScript is the use of fixed arguments, but this can be solved as found elsewhere on teh internets: Passing an array or a dictionary object to the function.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        Dim aryArguments&lt;br /&gt;        Call GetArguments(aryArguments)         'A function to set all arguments into an array&lt;br /&gt;        TestResult = fp(aryArguments)           'Pass the arguments to the function pointed to by the function pointer&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;And a quick example:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Public Function SumSquares(byRef aryArg)&lt;br /&gt;                &amp;nbsp;&amp;nbsp;Dim i, b&lt;br /&gt;                &amp;nbsp;&amp;nbsp;For i = lbound(anyArg) to ubound (aryArg)&lt;br /&gt;                &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;        b = b + aryArg(i)^2&lt;br /&gt;                &amp;nbsp;&amp;nbsp;Next i&lt;br /&gt;                &amp;nbsp;&amp;nbsp;SumSquares = b&lt;br /&gt;        End Function&lt;br /&gt;&lt;br /&gt;        Public Function SqrtSquares(byRef aryArg)&lt;br /&gt;                &amp;nbsp;&amp;nbsp;Dim i, b&lt;br /&gt;                &amp;nbsp;&amp;nbsp;For i = lbound(anyArg) to ubound (aryArg)&lt;br /&gt;                &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;        b = b + aryArg(i)^2&lt;br /&gt;                &amp;nbsp;&amp;nbsp;Next i&lt;br /&gt;        &amp;nbsp;&amp;nbsp;If b &gt;= 0 Then SqrtSquares = Sqr(b)&lt;br /&gt;        End Function&lt;br /&gt;&lt;br /&gt;        Public Function HandleKeyword(byval keyWord, byRef aryArg)&lt;br /&gt;                &amp;nbsp;&amp;nbsp;Dim fp&lt;br /&gt;&lt;br /&gt;                &amp;nbsp;&amp;nbsp;On error resume next&lt;br /&gt;                &amp;nbsp;&amp;nbsp;Set fp = GetRef(keyWord)&lt;br /&gt;                &amp;nbsp;&amp;nbsp;On error goto 0&lt;br /&gt;&lt;br /&gt;                &amp;nbsp;&amp;nbsp;If IsObject(fp) then&lt;br /&gt;                &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;        HandleKeyword = fp(aryArg)&lt;br /&gt;                &amp;nbsp;&amp;nbsp;Else&lt;br /&gt;                &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;        MsgBox "Keyword '" &amp;amp; KeyWord &amp;amp; "' could NOT be mapped to a valid function."&lt;br /&gt;                &amp;nbsp;&amp;nbsp;        HandleKeyword = "INVALID KEYWORD"&lt;br /&gt;                &amp;nbsp;&amp;nbsp;End if&lt;br /&gt;        End Function&lt;br /&gt;&lt;br /&gt;        Dim Arguments&lt;br /&gt;        Arguments = array(3, 4, 5)&lt;br /&gt;&lt;br /&gt;        MsgBox HandleKeyword("SumSquares", Arguments)   ' -&gt; shows "50"&lt;br /&gt;        MsgBox HandleKeyword("SqrtSquares", Arguments)  ' -&gt; shows ~ "7.07107"&lt;br /&gt;        MsgBox HandleKeyword("SumFactoerials", Arguments)       ' -&gt; shows "INVALID KEYWORD"&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1708518509752812818-3236917599836475460?l=automated-chaos.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://automated-chaos.blogspot.com/feeds/3236917599836475460/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1708518509752812818&amp;postID=3236917599836475460' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/3236917599836475460'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/3236917599836475460'/><link rel='alternate' type='text/html' href='http://automated-chaos.blogspot.com/2008/11/how-to-make-use-of-function-pointers-in.html' title='How to make use of Function Pointers in a Keyword Driven Approach'/><author><name>Bas M. Dam</name><uri>http://www.blogger.com/profile/07594616635957734329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_k--5h5XK9eM/SRCaSAcQ_ZI/AAAAAAAAAE4/HAhDr-NnwVg/s72-c/SuperBasic.png' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1708518509752812818.post-6130410365661806359</id><published>2008-10-14T09:53:00.008+02:00</published><updated>2008-10-14T11:18:38.786+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='VBScript'/><category scheme='http://www.blogger.com/atom/ns#' term='QTP'/><category scheme='http://www.blogger.com/atom/ns#' term='function calls'/><title type='text'>Parenthesis DO matter</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_k--5h5XK9eM/SPRiw1ig3bI/AAAAAAAAAEw/_BxONcPVi7g/s1600-h/c64_functionkeys.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_k--5h5XK9eM/SPRiw1ig3bI/AAAAAAAAAEw/_BxONcPVi7g/s200/c64_functionkeys.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5256935256193293746" /&gt;&lt;/a&gt;&lt;span style="font-family:verdana;"&gt;One thing I never knew: Parenthesis matter in QTP (and VBScript). And they surely make a difference. I discovered this during debugging a function call. There was different behaviour between these two function calls:&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;foo(bar)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;call foo(bar) &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;After some research over the internet and in QTP self, I came to the following conclusions: Passing an argument to a function surrounded by parenthesis means: "Protect me" or in other words: treat me as byVal even if it is defined in the function as byRef.&lt;br /&gt;&lt;br /&gt;Example:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;sub samplesub (a, b) ' a and b are by default handled as byRef&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;a = a + b&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;end sub&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;And this is happening when we call samplesub:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;x = 1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;y = 2&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;z = 4&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;samplesub x, y&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;samplesub (z), y&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;msgbox x ' displays "3"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;msgbox z ' displays "4" because z was passed as if it was passed byVal&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The same applies when you call a function:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;function samplefunc(c)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;c = c^2-1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;samplefunc = (c mod 2 = 1)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;end function&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;q = 8&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;samplefunc q&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;msgbox q ' returns 63&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;' When you accidentally forgot to call:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;p = 9&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;samplefunc(p)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;msgbox p ' returns 9, because p is returned byVal&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;' With call:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;r = 10&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;call samplefunc(r)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;msgbox r ' returns 99, because r is returned byRef&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;' With call and argument protected:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;s = 11&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;call samplefunc( (s) )&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;msgbox s ' returns 11, s is returned byVal&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;' And a last example of a function call with multiple argument with combined protection:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;call multifunc( (IamProtected), IamUnprotected )&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Rules in short:&lt;br /&gt;A sub/function call with an argument in protected mode overrides a byRef in the function.&lt;br /&gt;A sub/function call with an argument in unprotected mode is returned byRef by default unless it is overridden in the function by a byVal.&lt;br /&gt;An literal or const is always returned byVal.&lt;br /&gt;&lt;br /&gt;Syntax proposal:&lt;br /&gt;OK, it is ugly, but if you use parenthesis because they are part of the call, you should use them with spaces between the first and last argument and no space between the function:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;call f( a, b )&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If you want to use arguments in protected mode, you should use no spaces between the parenthesis and the arguments, but do use them between the function/sub and the parenthesis belonging to the function/sub call:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;f (a), (b)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;or&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="font-family:courier new;"&gt;call f( (a), (b) )&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1708518509752812818-6130410365661806359?l=automated-chaos.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://automated-chaos.blogspot.com/feeds/6130410365661806359/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1708518509752812818&amp;postID=6130410365661806359' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/6130410365661806359'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/6130410365661806359'/><link rel='alternate' type='text/html' href='http://automated-chaos.blogspot.com/2008/10/parenthesis-do-matter.html' title='Parenthesis DO matter'/><author><name>Bas M. Dam</name><uri>http://www.blogger.com/profile/07594616635957734329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_k--5h5XK9eM/SPRiw1ig3bI/AAAAAAAAAEw/_BxONcPVi7g/s72-c/c64_functionkeys.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1708518509752812818.post-4485591346720052719</id><published>2008-07-07T19:31:00.021+02:00</published><updated>2008-12-10T21:14:53.319+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='VBScript'/><category scheme='http://www.blogger.com/atom/ns#' term='QTP'/><category scheme='http://www.blogger.com/atom/ns#' term='Reference Card'/><category scheme='http://www.blogger.com/atom/ns#' term='coding'/><title type='text'>QTP Quick Reference Card</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left;" src="http://4.bp.blogspot.com/_k--5h5XK9eM/SHJeN9v8ZMI/AAAAAAAAADY/UicZI2tkdeQ/s320/Reference+Guide.png" alt="" id="BLOGGER_PHOTO_ID_5220338512082789570" border="0" /&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:verdana;"&gt;&lt;br /&gt;&lt;br /&gt;As a WinRunner user, I've got very used to the concept of automated testing. Changing to QTP was not much of a problem except for the language notation. For example, the thing I always do wrong:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Select Case &lt;span style="font-style: italic;"&gt;anyVariable&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Case 1,2&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;...&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Case Default ...  ***CRASH***&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:verdana;"&gt;And you'll only discover it at runtime, because Default is displayed in blue as it is used to set the default property for a class. ('Default' is the 'Case Else' in C/C++ or TSL).&lt;br /&gt;&lt;br /&gt;For all advanced users having trouble with VBScript notation on the expert view, I want to share my QTP Quick Reference Card (also called Cheat Sheet). It displays all general functions you'll want to use in QTP.&lt;br /&gt;&lt;br /&gt;The PNG version:&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_k--5h5XK9eM/SHJe_kOQP3I/AAAAAAAAADg/0JKj-lZ2w-k/s1600-h/QTP+quick+reference+v1.1.PNG"&gt;&lt;img style="cursor: pointer;" src="http://3.bp.blogspot.com/_k--5h5XK9eM/SHJe_kOQP3I/AAAAAAAAADg/0JKj-lZ2w-k/s200/QTP+quick+reference+v1.1.PNG" alt="" id="BLOGGER_PHOTO_ID_5220339364224057202" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:verdana;"&gt;&lt;br /&gt;Or the smaller and more portable PDF version:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://automatedchaos.googlepages.com/QTPquickreferencecardv1.1a.pdf"&gt;&lt;img style="cursor: pointer;" src="http://2.bp.blogspot.com/_k--5h5XK9eM/SHJYTEgdIcI/AAAAAAAAADQ/FQZ6L2wF0mQ/s320/pdf_icon_test.jpg" alt="" id="BLOGGER_PHOTO_ID_5220332002726453698" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;If you have any comments or additions on this document, please leave a message in the comments.&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1708518509752812818-4485591346720052719?l=automated-chaos.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://automated-chaos.blogspot.com/feeds/4485591346720052719/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1708518509752812818&amp;postID=4485591346720052719' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/4485591346720052719'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/4485591346720052719'/><link rel='alternate' type='text/html' href='http://automated-chaos.blogspot.com/2008/07/qtp-quick-reference-card.html' title='QTP Quick Reference Card'/><author><name>Bas M. Dam</name><uri>http://www.blogger.com/profile/07594616635957734329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_k--5h5XK9eM/SHJeN9v8ZMI/AAAAAAAAADY/UicZI2tkdeQ/s72-c/Reference+Guide.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1708518509752812818.post-2979381782273416265</id><published>2008-07-01T12:09:00.013+02:00</published><updated>2008-12-10T21:14:53.391+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tooltips'/><category scheme='http://www.blogger.com/atom/ns#' term='winrunner'/><category scheme='http://www.blogger.com/atom/ns#' term='coding'/><title type='text'>Get the text from a tooltip with WinRunner</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_k--5h5XK9eM/SGoIF1r5fpI/AAAAAAAAACw/AptQppQKqzM/s1600-h/tooltip.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_k--5h5XK9eM/SGoIF1r5fpI/AAAAAAAAACw/AptQppQKqzM/s320/tooltip.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5217992014665711250" /&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:verdana;"&gt;Getting the text form a standard tooltip in an HTML document with WinRunner took me some time to figure out. Actually it is one small statement that will do the trick, but finding out what statement kept me searching for a while. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;win_get_info("{class: window, MSW_class:&amp;#92;"tooltips_class32&amp;#92;",displayed: 1}","text",text);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;This will do it. Really.&lt;br /&gt;&lt;br /&gt;And to wrap it into a function:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&lt;br /&gt;public&amp;nbsp;function&amp;nbsp;get_tooltip(object,&amp;nbsp;out&amp;nbsp;text)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;auto&amp;nbsp;hwnd,&amp;nbsp;rc;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;First&amp;nbsp;set&amp;nbsp;the&amp;nbsp;cursor&amp;nbsp;position&amp;nbsp;to&amp;nbsp;the&amp;nbsp;left&amp;nbsp;corner&amp;nbsp;of&amp;nbsp;the&amp;nbsp;screen.&amp;nbsp;When&amp;nbsp;you&amp;nbsp;don't&amp;nbsp;do&amp;nbsp;this,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;a&amp;nbsp;formerly&amp;nbsp;captured&amp;nbsp;tooltip&amp;nbsp;can&amp;nbsp;be&amp;nbsp;hovering&amp;nbsp;over&amp;nbsp;the&amp;nbsp;object,&amp;nbsp;making&amp;nbsp;it&amp;nbsp;impossible&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;for&amp;nbsp;WinRunner&amp;nbsp;to&amp;nbsp;locate&amp;nbsp;it.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;rc&amp;nbsp;=&amp;nbsp;move_locator_abs(1,&amp;nbsp;1);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;Move&amp;nbsp;the&amp;nbsp;cursor&amp;nbsp;to&amp;nbsp;the&amp;nbsp;object&amp;nbsp;containing&amp;nbsp;the&amp;nbsp;tooltip&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;web_cursor_to_obj(object,&amp;nbsp;1,&amp;nbsp;1);&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;Move&amp;nbsp;the&amp;nbsp;cursor&amp;nbsp;back&amp;nbsp;and&amp;nbsp;forth&amp;nbsp;to&amp;nbsp;trigger&amp;nbsp;the&amp;nbsp;tooltip&amp;nbsp;to&amp;nbsp;pop&amp;nbsp;up&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;move_locator_rel(0,1);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;move_locator_rel(0,-1);&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;Wait&amp;nbsp;for&amp;nbsp;the&amp;nbsp;tooltip.&amp;nbsp;This&amp;nbsp;is&amp;nbsp;time&amp;nbsp;consuming,&amp;nbsp;something&amp;nbsp;to&amp;nbsp;keep&amp;nbsp;in&amp;nbsp;mind&amp;nbsp;when&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;you&amp;nbsp;want&amp;nbsp;to&amp;nbsp;use&amp;nbsp;this&amp;nbsp;function&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;wait(2);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;Check&amp;nbsp;on&amp;nbsp;visibility&amp;nbsp;of&amp;nbsp;the&amp;nbsp;tooltip&amp;nbsp;window,&amp;nbsp;otherwise&amp;nbsp;a&amp;nbsp;standard&amp;nbsp;tooltip&amp;nbsp;does&amp;nbsp;not&amp;nbsp;exist&amp;nbsp;for&amp;nbsp;this&amp;nbsp;object&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if((rc&amp;nbsp;=&amp;nbsp;win_exists("{class:&amp;nbsp;window,&amp;nbsp;MSW_class:&amp;nbsp;&amp;#92;"tooltips_class32&amp;#92;",displayed:&amp;nbsp;1}"))&amp;nbsp;==&amp;nbsp;E_OK)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;Capture&amp;nbsp;the&amp;nbsp;text&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;win_get_info("{class:&amp;nbsp;window,&amp;nbsp;MSW_class:&amp;nbsp;&amp;#92;"tooltips_class32&amp;#92;",displayed:&amp;nbsp;1}","text",text);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;rc;&lt;br /&gt;}&lt;br /&gt;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Keep in mind, this only works with standard tooltips, recognizable on the title='[text]' attribute in the HTML tag (not always visible when CSS is used). When the tooltip is a customized tooltip created by some JavaScript, most probably it is created as a frame object and you'll have to capture the text of that frame object in stead.&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1708518509752812818-2979381782273416265?l=automated-chaos.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://automated-chaos.blogspot.com/feeds/2979381782273416265/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1708518509752812818&amp;postID=2979381782273416265' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/2979381782273416265'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/2979381782273416265'/><link rel='alternate' type='text/html' href='http://automated-chaos.blogspot.com/2008/07/get-text-from-tooltip-in-winrunner.html' title='Get the text from a tooltip with WinRunner'/><author><name>Bas M. Dam</name><uri>http://www.blogger.com/profile/07594616635957734329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_k--5h5XK9eM/SGoIF1r5fpI/AAAAAAAAACw/AptQppQKqzM/s72-c/tooltip.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1708518509752812818.post-1335812067229536227</id><published>2008-07-01T10:14:00.007+02:00</published><updated>2008-12-10T21:14:54.441+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='automated testing'/><category scheme='http://www.blogger.com/atom/ns#' term='testnet'/><title type='text'>TestNet Voorjaars Event</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_k--5h5XK9eM/SGnt_CwtM_I/AAAAAAAAACo/YyMWSw_y6oQ/s1600-h/testnet.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://1.bp.blogspot.com/_k--5h5XK9eM/SGnt_CwtM_I/AAAAAAAAACo/YyMWSw_y6oQ/s320/testnet.jpg" alt="" id="BLOGGER_PHOTO_ID_5217963310614131698" border="0" /&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:verdana;"&gt;Yesterday was the day of the TestNet Voorjaars Event. &lt;a href="http://www.testnet.org/"&gt;TestNet&lt;/a&gt; is the national Dutch organization for testers. There were some great presentations and off course the warm bath experience of seeing lots of old collegues. That is one advantage of being Dutch: The test community is not very large in numbers. TestNet has around 1200 members, while the test community is as large of 6000 professional testers.&lt;br /&gt;&lt;br /&gt;The theme was TestTooling, so I fitted well. Actually, I was invited to do a presentation, which I did with Marc Koper, a collegue of mine.&lt;br /&gt;&lt;br /&gt;If you are interested in the presentations (some real good ones included), you can find them at the &lt;a href="http://www.testnet.org/Produktie/Bibliotheek/Presentaties.html"&gt;TestNet Library Page&lt;/a&gt;. However, most of them are in Dutch.&lt;br /&gt;If you are especially interested in our presentation, it is called "&lt;a href="http://www.testnet.org/Produktie/Bibliotheek/Presentaties%20voorjaar%202008/AToolwithafoolMarcKoper.pdf"&gt;A tool with a fool is only a tool&lt;/a&gt;". It is an introduction in how you can set op test automation (Performance and Test execution) in a test organisation with lots of tips and tricks. Well, for the best tips and tricks, you should have been there, but later this month, I will put some of them on my blog. &lt;br /&gt;&lt;br /&gt;Update: The &lt;a href="http://www.performancearchitecten.nl/wordpress/wp-content/uploads/2008/07/a-tool-with-a-fool.pdf"&gt;abstract&lt;/a&gt; of our presentation&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1708518509752812818-1335812067229536227?l=automated-chaos.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://automated-chaos.blogspot.com/feeds/1335812067229536227/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1708518509752812818&amp;postID=1335812067229536227' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/1335812067229536227'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/1335812067229536227'/><link rel='alternate' type='text/html' href='http://automated-chaos.blogspot.com/2008/07/testnet-voorjaars-event.html' title='TestNet Voorjaars Event'/><author><name>Bas M. Dam</name><uri>http://www.blogger.com/profile/07594616635957734329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_k--5h5XK9eM/SGnt_CwtM_I/AAAAAAAAACo/YyMWSw_y6oQ/s72-c/testnet.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1708518509752812818.post-4459919153140064746</id><published>2008-06-28T11:28:00.007+02:00</published><updated>2008-12-10T21:14:54.791+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='VBScript'/><category scheme='http://www.blogger.com/atom/ns#' term='coding'/><title type='text'>This Weekend's Code Play</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_k--5h5XK9eM/SGYsQZtdPII/AAAAAAAAACg/xl8XpTdxb-M/s1600-h/c64+loopz.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_k--5h5XK9eM/SGYsQZtdPII/AAAAAAAAACg/xl8XpTdxb-M/s320/c64+loopz.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5216905878646373506" /&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:verdana;"&gt;Right now, I am almost finishing &lt;a href="http://en.wikipedia.org/wiki/G%C3%B6del%2C_Escher%2C_Bach"&gt;Gödel, Escher, Bach&lt;/a&gt; written by &lt;a href="http://en.wikipedia.org/wiki/Douglas_Hofstadter"&gt;Douglas R. Hofstadter&lt;/a&gt;. Well, I'm on page 614, so I still have around 200 pages to go, but for me it feels like almost finishing. And this inspired me to a little piece of code in VBScript:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;" &gt;Dim&amp;nbsp;a,&amp;nbsp;p&amp;nbsp;&lt;br /&gt;Dim&amp;nbsp;YmPool(8)&lt;br /&gt;&lt;br /&gt;Do&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;mIP&amp;nbsp;=&amp;nbsp;afNe(a+3)*2&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;NextElem&amp;nbsp;=&amp;nbsp;el&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;If&amp;nbsp;YmPool((a+2)*3)&amp;nbsp;=&amp;nbsp;aDig&amp;nbsp;Or&amp;nbsp;p&amp;nbsp;=&amp;nbsp;1&amp;nbsp;Then&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;InTest&amp;nbsp;=&amp;nbsp;a&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;LitNuod&amp;nbsp;"nametag",&amp;nbsp;"Gateman"&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Do&amp;nbsp;Until&amp;nbsp;a&amp;nbsp;=&amp;nbsp;t&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Set&amp;nbsp;NineHt1&amp;nbsp;=&amp;nbsp;ProgId&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;a&amp;nbsp;=&amp;nbsp;(3*(2+a))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Loop&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MyFile&amp;nbsp;=&amp;nbsp;Me&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Let&amp;nbsp;xEn&amp;nbsp;=&amp;nbsp;2*(3+a)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;End&amp;nbsp;If&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;a&amp;nbsp;=&amp;nbsp;PI&amp;nbsp;Mod&amp;nbsp;(8)&lt;br /&gt;Loop&amp;nbsp;&lt;br /&gt;&lt;br /&gt;myMid&amp;nbsp;p,&amp;nbsp;amId &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Do you see the catch?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;My next challenge: Write an actual snippet in VBScript this way that makes sense and that is actually usable.&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1708518509752812818-4459919153140064746?l=automated-chaos.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://automated-chaos.blogspot.com/feeds/4459919153140064746/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1708518509752812818&amp;postID=4459919153140064746' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/4459919153140064746'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/4459919153140064746'/><link rel='alternate' type='text/html' href='http://automated-chaos.blogspot.com/2008/06/this-weekends-code-play.html' title='This Weekend&apos;s Code Play'/><author><name>Bas M. Dam</name><uri>http://www.blogger.com/profile/07594616635957734329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_k--5h5XK9eM/SGYsQZtdPII/AAAAAAAAACg/xl8XpTdxb-M/s72-c/c64+loopz.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1708518509752812818.post-8056848830213252777</id><published>2008-06-25T19:33:00.012+02:00</published><updated>2008-12-10T21:14:55.635+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='VBScript'/><category scheme='http://www.blogger.com/atom/ns#' term='QTP'/><category scheme='http://www.blogger.com/atom/ns#' term='IBAN'/><category scheme='http://www.blogger.com/atom/ns#' term='coding'/><title type='text'>QTP: IBAN validation in VBScript</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_k--5h5XK9eM/SGKKSBsKuHI/AAAAAAAAACY/xAmkINqunJ0/s1600-h/C64_iban.jpeg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_k--5h5XK9eM/SGKKSBsKuHI/AAAAAAAAACY/xAmkINqunJ0/s320/C64_iban.jpeg" border="0" alt=""id="BLOGGER_PHOTO_ID_5215883360744421490" /&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:verdana;"&gt;&lt;/span&gt; &lt;span style="font-family:verdana;"&gt; &lt;/span&gt; &lt;span style="font-family:verdana;"&gt;IBAN stands for &lt;a href="http://en.wikipedia.org/wiki/IBAN"&gt;International Bank Account Number&lt;/a&gt; and is the old new toy of the banking community. Also hot in Europe because of &lt;a href="http://en.wikipedia.org/wiki/Single_Euro_Payments_Area"&gt;SEPA&lt;/a&gt;. IBAN should make life easier, and maybe it does. For IT guys, IBAN is just another standard. And despite IT guys like standards (that is why they have so many of them), IBAN is a standard designed by the banking people making things a little more complicated.&lt;/span&gt; &lt;span style="font-family:verdana;"&gt; &lt;/span&gt; &lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;The things you want to do with IBAN is validate it or just calculate the checksum on your own. The fo&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:verdana;"&gt;rmula for the checksum is not very complex, but has some twists in it. For example, when dealing with Alpha characters, the A is transposed to 10, the B to 11 etc. In the IT world, we would transpose A to 65, B to 66… The things you don't want is validate them exactly right for for every country on this little planet. Maybe they want it, but definitely, you don't. And if they want it, get yo&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:verdana;"&gt;urself a new toy called SOAP and connect to it through a &lt;a href="http://www.iban-bic.com/integrate.html?&amp;amp;L=2"&gt;service&lt;/a&gt;.&lt;/span&gt; &lt;span style="font-family:verdana;"&gt; &lt;/span&gt; &lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;After searching the internet, I discovered that code for IBAN validation through any Visual Basic language was rare. I gathered &lt;a href="http://www.eggheadcafe.com/forumarchives/Excel/Jun2005/post23281510.asp"&gt;the&lt;/a&gt; &lt;a href="http://exceltips.vitalnews.com/Pages/T003302_Large_Numbers_in_the_MOD_Function.html"&gt;snippets&lt;/a&gt; &lt;a href="http://www.morfoedro.it/doc.php?n=219&amp;amp;lang=en"&gt;I&lt;/a&gt; &lt;a href="http://www.leopoldnet.de/file/iban.html"&gt;found&lt;/a&gt; &lt;a href="http://www.pcreview.co.uk/forums/thread-1711706.php"&gt;useful&lt;/a&gt; and created my own IBAN functions.&lt;/span&gt; &lt;span style="font-family:verdana;"&gt;&lt;br /&gt;&lt;br /&gt;How it works is all in the comments in the code, keeping your scripts maintainable and documented if you want to use it:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;'&amp;nbsp;This&amp;nbsp;code&amp;nbsp;was&amp;nbsp;created&amp;nbsp;by&amp;nbsp;Bas&amp;nbsp;M.&amp;nbsp;Dam&amp;nbsp;and&amp;nbsp;first&amp;nbsp;published&amp;nbsp;on&lt;br /&gt;'&amp;nbsp;http://automated-chaos.blogspot.com&lt;br /&gt;'&amp;nbsp;You&amp;nbsp;can&amp;nbsp;use&amp;nbsp;and&amp;nbsp;distribute&amp;nbsp;this&amp;nbsp;code&amp;nbsp;freely,&amp;nbsp;as&amp;nbsp;long&amp;nbsp;as&amp;nbsp;you&lt;br /&gt;'&amp;nbsp;keep&amp;nbsp;this&amp;nbsp;commentblock&amp;nbsp;intact.&lt;br /&gt;&lt;br /&gt;'&amp;nbsp;RETRIEVING&amp;nbsp;THE&amp;nbsp;CHECKSUM&lt;br /&gt;'&amp;nbsp;There&amp;nbsp;are&amp;nbsp;two&amp;nbsp;methods&amp;nbsp;to&amp;nbsp;get&amp;nbsp;the&amp;nbsp;checksum.&amp;nbsp;The&amp;nbsp;first&amp;nbsp;is&amp;nbsp;the&lt;br /&gt;'&amp;nbsp;one&amp;nbsp;used&amp;nbsp;in&amp;nbsp;automated&amp;nbsp;processes&amp;nbsp;where&amp;nbsp;there&amp;nbsp;is&amp;nbsp;an&amp;nbsp;iban&amp;nbsp;prototype.&lt;br /&gt;'&amp;nbsp;the&amp;nbsp;checksum&amp;nbsp;is&amp;nbsp;replaced&amp;nbsp;by&amp;nbsp;zeros:&lt;br /&gt;'&amp;nbsp;MsgBox&amp;nbsp;getIBANchecksum("LC00BANK1234567890",&amp;nbsp;empty)&amp;nbsp;'returns&amp;nbsp;86&lt;br /&gt;&lt;br /&gt;'&amp;nbsp;The&amp;nbsp;other&amp;nbsp;way&amp;nbsp;is&amp;nbsp;a&amp;nbsp;more&amp;nbsp;user&amp;nbsp;fiendly&amp;nbsp;appraoch&amp;nbsp;if&amp;nbsp;only&amp;nbsp;the&amp;nbsp;separate&lt;br /&gt;'&amp;nbsp;segments&amp;nbsp;are&amp;nbsp;known&amp;nbsp;like&amp;nbsp;bank&amp;nbsp;code&amp;nbsp;or&amp;nbsp;clearing&amp;nbsp;house:&lt;br /&gt;'&amp;nbsp;MsgBox&amp;nbsp;getIBANchecksum("BANK1234567890",&amp;nbsp;"LC")&amp;nbsp;'returns&amp;nbsp;86&lt;br /&gt;&lt;br /&gt;'&amp;nbsp;CREATE&amp;nbsp;AN&amp;nbsp;IBAN&amp;nbsp;NUMBER&lt;br /&gt;'&amp;nbsp;This&amp;nbsp;is&amp;nbsp;implemented&amp;nbsp;in&amp;nbsp;the&amp;nbsp;makeIBAN()&amp;nbsp;function&amp;nbsp;for&amp;nbsp;your&amp;nbsp;convenience&lt;br /&gt;'&amp;nbsp;Msgbox&amp;nbsp;makeIBAN("LC",&amp;nbsp;"BANK",&amp;nbsp;empty,&amp;nbsp;"1234567890")&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;returns&amp;nbsp;LC86BANK1234567890&lt;br /&gt;&lt;br /&gt;'&amp;nbsp;Or&amp;nbsp;just&amp;nbsp;the&amp;nbsp;simple&amp;nbsp;implementation:&lt;br /&gt;'&amp;nbsp;Msgbox&amp;nbsp;makeIBAN("LCBANK1234567890",&amp;nbsp;empty,&amp;nbsp;empty,&amp;nbsp;empty)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;returns&amp;nbsp;LC86BANK1234567890&lt;br /&gt;&lt;br /&gt;'&amp;nbsp;CHECK&amp;nbsp;AN&amp;nbsp;IBAN&amp;nbsp;NUMBER&lt;br /&gt;'&amp;nbsp;And&amp;nbsp;finally,&amp;nbsp;you&amp;nbsp;want&amp;nbsp;to&amp;nbsp;check&amp;nbsp;if&amp;nbsp;something&amp;nbsp;is&amp;nbsp;IBAN.&amp;nbsp;You&amp;nbsp;can&lt;br /&gt;'&amp;nbsp;use&amp;nbsp;the&amp;nbsp;getIBANchecksum&amp;nbsp;function&amp;nbsp;for&amp;nbsp;it.&amp;nbsp;If&amp;nbsp;the&amp;nbsp;result&amp;nbsp;is&amp;nbsp;97,&lt;br /&gt;'&amp;nbsp;then&amp;nbsp;you&amp;nbsp;have&amp;nbsp;a&amp;nbsp;real&amp;nbsp;IBAN,&amp;nbsp;when&amp;nbsp;it&amp;nbsp;returns&amp;nbsp;-1,&amp;nbsp;there&amp;nbsp;is&amp;nbsp;something&lt;br /&gt;'&amp;nbsp;wrong&amp;nbsp;with&amp;nbsp;the&amp;nbsp;IBAN&amp;nbsp;and&amp;nbsp;if&amp;nbsp;it&amp;nbsp;returns&amp;nbsp;another&amp;nbsp;number,&amp;nbsp;the&amp;nbsp;checksum&lt;br /&gt;'&amp;nbsp;is&amp;nbsp;not&amp;nbsp;correct&lt;br /&gt;'&amp;nbsp;Msgbox&amp;nbsp;getIBANchecksum("LC86BANK1234567890",&amp;nbsp;empty)&amp;nbsp;'returns&amp;nbsp;97&lt;br /&gt;'&amp;nbsp;Msgbox&amp;nbsp;getIBANchecksum("LC68BANK1234567890",&amp;nbsp;empty)&amp;nbsp;'returns&amp;nbsp;18&lt;br /&gt;'&amp;nbsp;Msgbox&amp;nbsp;getIBANchecksum("LC68BANK1234567891",&amp;nbsp;empty)&amp;nbsp;'returns&amp;nbsp;88&lt;br /&gt;'&amp;nbsp;Msgbox&amp;nbsp;getIBANchecksum("LC86BANK123456789%",&amp;nbsp;empty)&amp;nbsp;'returns&amp;nbsp;-1&lt;br /&gt;&lt;br /&gt;'&amp;nbsp;To&amp;nbsp;do&amp;nbsp;this&amp;nbsp;the&amp;nbsp;simple&amp;nbsp;way,&amp;nbsp;you&amp;nbsp;can&amp;nbsp;make&amp;nbsp;use&amp;nbsp;of&amp;nbsp;the&amp;nbsp;isIBAN()&amp;nbsp;function&lt;br /&gt;'&amp;nbsp;that&amp;nbsp;simply&amp;nbsp;returns&amp;nbsp;True&amp;nbsp;or&amp;nbsp;False:&lt;br /&gt;'&amp;nbsp;Msgbox&amp;nbsp;isIBAN("LC86BANK1234567890")&amp;nbsp;'returns&amp;nbsp;True&lt;br /&gt;'&amp;nbsp;Msgbox&amp;nbsp;isIBAN("LC68BANK1234567890")&amp;nbsp;'returns&amp;nbsp;False&lt;br /&gt;'&amp;nbsp;Msgbox&amp;nbsp;isIBAN("LC86BANK123456789%")&amp;nbsp;'returns&amp;nbsp;False&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;'&amp;nbsp;SPECIAL&amp;nbsp;CHARACTERS&lt;br /&gt;'&amp;nbsp;You&amp;nbsp;can&amp;nbsp;use&amp;nbsp;typographical&amp;nbsp;characters&amp;nbsp;as&amp;nbsp;stated&amp;nbsp;in&amp;nbsp;the&amp;nbsp;skipChars&amp;nbsp;string.&lt;br /&gt;'&amp;nbsp;For&amp;nbsp;now,&amp;nbsp;the&amp;nbsp;following&amp;nbsp;characters&amp;nbsp;can&amp;nbsp;be&amp;nbsp;used:&amp;nbsp;space.-_,/&lt;br /&gt;'&amp;nbsp;These&amp;nbsp;characters&amp;nbsp;are&amp;nbsp;often&amp;nbsp;used&amp;nbsp;to&amp;nbsp;make&amp;nbsp;an&amp;nbsp;IBAN&amp;nbsp;more&amp;nbsp;readible,&amp;nbsp;but&amp;nbsp;are&lt;br /&gt;'&amp;nbsp;not&amp;nbsp;taken&amp;nbsp;into&amp;nbsp;the&amp;nbsp;checksum&amp;nbsp;calculation.&amp;nbsp;between&amp;nbsp;the&amp;nbsp;landcode&lt;br /&gt;'&amp;nbsp;and&amp;nbsp;checksum,&amp;nbsp;never&amp;nbsp;a&amp;nbsp;typographical&amp;nbsp;character&amp;nbsp;can&amp;nbsp;be&amp;nbsp;used.&lt;br /&gt;'&amp;nbsp;Msgbox&amp;nbsp;isIBAN("LC86&amp;nbsp;BANK&amp;nbsp;1234&amp;nbsp;5678&amp;nbsp;90")&amp;nbsp;'returns&amp;nbsp;True&lt;br /&gt;'&amp;nbsp;Msgbox&amp;nbsp;isIBAN("LC86BANK1234.56.78.90")&amp;nbsp;&amp;nbsp;'returns&amp;nbsp;True&lt;br /&gt;'&amp;nbsp;Msgbox&amp;nbsp;isIBAN("LC-86-BANK-1234-567890")&amp;nbsp;'returns&amp;nbsp;False,&amp;nbsp;there&amp;nbsp;can&amp;nbsp;not&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'be&amp;nbsp;a&amp;nbsp;separation&amp;nbsp;char&amp;nbsp;between&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'landcode&amp;nbsp;and&amp;nbsp;checksum.&lt;br /&gt;'&amp;nbsp;Msgbox&amp;nbsp;isIBAN("LC*86*BANK*1234*567890")&amp;nbsp;'returns&amp;nbsp;False,&amp;nbsp;*&amp;nbsp;is&amp;nbsp;not&amp;nbsp;a&amp;nbsp;special&amp;nbsp;char&lt;br /&gt;&lt;br /&gt;'&amp;nbsp;Function&amp;nbsp;to&amp;nbsp;check&amp;nbsp;on&amp;nbsp;an&amp;nbsp;IBAN&lt;br /&gt;Public&amp;nbsp;Function&amp;nbsp;isIBAN(sIban)&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;isIBAN&amp;nbsp;=&amp;nbsp;(getIBANchecksum(sIban,&amp;nbsp;empty)&amp;nbsp;=&amp;nbsp;97)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;End&amp;nbsp;Function&lt;br /&gt;&lt;br /&gt;'&amp;nbsp;Function&amp;nbsp;to&amp;nbsp;create&amp;nbsp;an&amp;nbsp;IBAN.&amp;nbsp;Any&amp;nbsp;of&amp;nbsp;the&amp;nbsp;arguments&amp;nbsp;can&amp;nbsp;be&amp;nbsp;empty,&amp;nbsp;as&lt;br /&gt;'&amp;nbsp;long&amp;nbsp;as&amp;nbsp;the&amp;nbsp;first&amp;nbsp;not&amp;nbsp;empty&amp;nbsp;argument&amp;nbsp;starts&amp;nbsp;with&amp;nbsp;the&amp;nbsp;landcode&lt;br /&gt;Public&amp;nbsp;function&amp;nbsp;makeIBAN(landcode,&amp;nbsp;bankcode,&amp;nbsp;sortcode,&amp;nbsp;accountnr)&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dim&amp;nbsp;realLandcode,&amp;nbsp;sPurged&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sPurged&amp;nbsp;=&amp;nbsp;mid(landcode&amp;nbsp;&amp;&amp;nbsp;bankcode&amp;nbsp;&amp;&amp;nbsp;sortcode&amp;nbsp;&amp;&amp;nbsp;accountnr,&amp;nbsp;3)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;realLandcode&amp;nbsp;=&amp;nbsp;left(landcode&amp;nbsp;&amp;&amp;nbsp;bankcode&amp;nbsp;&amp;&amp;nbsp;sortcode&amp;nbsp;&amp;&amp;nbsp;accountnr,&amp;nbsp;2)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;makeIBAN&amp;nbsp;=&amp;nbsp;realLandcode&amp;nbsp;&amp;&amp;nbsp;getIBANchecksum(sPurged,&amp;nbsp;realLandcode)&amp;nbsp;&amp;&amp;nbsp;sPurged&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;End&amp;nbsp;Function&lt;br /&gt;&lt;br /&gt;'&amp;nbsp;Function&amp;nbsp;to&amp;nbsp;get&amp;nbsp;an&amp;nbsp;IBAN&amp;nbsp;checksum.&amp;nbsp;Landcode&amp;nbsp;can&amp;nbsp;be&amp;nbsp;empty,&amp;nbsp;but&amp;nbsp;then,&amp;nbsp;the&amp;nbsp;landcode&lt;br /&gt;'&amp;nbsp;must&amp;nbsp;be&amp;nbsp;included&amp;nbsp;in&amp;nbsp;the&amp;nbsp;first&amp;nbsp;two&amp;nbsp;characters&amp;nbsp;of&amp;nbsp;sIban,&amp;nbsp;followed&amp;nbsp;by&amp;nbsp;two&amp;nbsp;zero's&lt;br /&gt;Public&amp;nbsp;Function&amp;nbsp;getIBANchecksum(sIban,&amp;nbsp;landcode)&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;Dim&amp;nbsp;sLCCS&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'Land&amp;nbsp;Code&amp;nbsp;and&amp;nbsp;Check&amp;nbsp;Sum&lt;br /&gt;&amp;nbsp;&amp;nbsp;Dim&amp;nbsp;sIbanMixed&lt;br /&gt;&amp;nbsp;&amp;nbsp;Dim&amp;nbsp;sIbanDigits&lt;br /&gt;&amp;nbsp;&amp;nbsp;Dim&amp;nbsp;char&lt;br /&gt;&amp;nbsp;&amp;nbsp;Dim&amp;nbsp;i&lt;br /&gt;&amp;nbsp;&amp;nbsp;Dim&amp;nbsp;skipChars&lt;br /&gt;&amp;nbsp;&amp;nbsp;skipChars&amp;nbsp;=&amp;nbsp;"&amp;nbsp;.-_,/"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;'&amp;nbsp;Marginal&amp;nbsp;length&amp;nbsp;check&lt;br /&gt;&amp;nbsp;&amp;nbsp;If&amp;nbsp;Len(sIban)&amp;nbsp;&lt;&amp;nbsp;5&amp;nbsp;Or&amp;nbsp;Len(sIban)&amp;nbsp;&gt;&amp;nbsp;35&amp;nbsp;Then&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;getIBANchecksum&amp;nbsp;=&amp;nbsp;-1&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Exit&amp;nbsp;Function&lt;br /&gt;&amp;nbsp;&amp;nbsp;End&amp;nbsp;If&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;If&amp;nbsp;landcode&amp;nbsp;=&amp;nbsp;empty&amp;nbsp;Then&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sLCCS&amp;nbsp;=&amp;nbsp;Left(sIban,&amp;nbsp;4)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;&amp;nbsp;&amp;nbsp;Extract&amp;nbsp;land&amp;nbsp;code&amp;nbsp;and&amp;nbsp;check&amp;nbsp;sum&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sIbanMixed&amp;nbsp;=&amp;nbsp;Right(sIban,&amp;nbsp;Len(sIban)&amp;nbsp;-&amp;nbsp;4)&amp;nbsp;&amp;&amp;nbsp;UCase(sLCCS)&lt;br /&gt;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sLCCS&amp;nbsp;=&amp;nbsp;landcode&amp;nbsp;&amp;&amp;nbsp;"00"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sIbanMixed&amp;nbsp;=&amp;nbsp;sIban&amp;nbsp;&amp;&amp;nbsp;UCase(sLCCS)&lt;br /&gt;&amp;nbsp;&amp;nbsp;End&amp;nbsp;If&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;For&amp;nbsp;i&amp;nbsp;=&amp;nbsp;1&amp;nbsp;To&amp;nbsp;Len(sIbanMixed)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;char&amp;nbsp;=&amp;nbsp;Mid(sIbanMixed,&amp;nbsp;i,&amp;nbsp;1)&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'Check&amp;nbsp;on&amp;nbsp;digits&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;If&amp;nbsp;IsNumeric(char)&amp;nbsp;Then&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sIbanDigits&amp;nbsp;=&amp;nbsp;sIbanDigits&amp;nbsp;&amp;&amp;nbsp;char&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'Check&amp;nbsp;on&amp;nbsp;typographical&amp;nbsp;characters&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;elseif&amp;nbsp;instr(skipChars,&amp;nbsp;char)&amp;nbsp;Then&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'skip&amp;nbsp;this&amp;nbsp;character,&amp;nbsp;but&amp;nbsp;continue&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'Check&amp;nbsp;on&amp;nbsp;non-uppercase&amp;nbsp;other&amp;nbsp;characters&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;elseif&amp;nbsp;Asc(char)&amp;nbsp;&lt;&amp;nbsp;65&amp;nbsp;OR&amp;nbsp;Asc(char)&amp;nbsp;&gt;&amp;nbsp;90&amp;nbsp;then&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;getIBANchecksum&amp;nbsp;=&amp;nbsp;-1&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Exit&amp;nbsp;function&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'Transform&amp;nbsp;characters&amp;nbsp;to&amp;nbsp;digits&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sIbanDigits&amp;nbsp;=&amp;nbsp;sIbanDigits&amp;nbsp;&amp;&amp;nbsp;(Asc(char)&amp;nbsp;-&amp;nbsp;55)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;End&amp;nbsp;If&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Next&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;getIBANchecksum&amp;nbsp;=&amp;nbsp;98&amp;nbsp;-&amp;nbsp;largeModulus(sIbanDigits,&amp;nbsp;97)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;End&amp;nbsp;Function&lt;br /&gt;&lt;br /&gt;'&amp;nbsp;Calculates&amp;nbsp;the&amp;nbsp;modulus&amp;nbsp;of&amp;nbsp;large&amp;nbsp;integers&amp;nbsp;that&amp;nbsp;are&amp;nbsp;actually&lt;br /&gt;'&amp;nbsp;strings.&amp;nbsp;Also&amp;nbsp;usefull&amp;nbsp;for&amp;nbsp;implementation&amp;nbsp;in&amp;nbsp;Excel&amp;nbsp;VBA&lt;br /&gt;'&amp;nbsp;(there&amp;nbsp;is&amp;nbsp;a&amp;nbsp;known&amp;nbsp;bug&amp;nbsp;in&amp;nbsp;Excel&amp;nbsp;and&amp;nbsp;large&amp;nbsp;number&amp;nbsp;modulus)&lt;br /&gt;Private&amp;nbsp;Function&amp;nbsp;largeModulus(sNumber,&amp;nbsp;modulus)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Dim&amp;nbsp;i,&amp;nbsp;sRebuild(),&amp;nbsp;j,&amp;nbsp;r&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;j&amp;nbsp;=&amp;nbsp;0&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sNumber&amp;nbsp;=&amp;nbsp;cStr(sNumber)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;For&amp;nbsp;i&amp;nbsp;=&amp;nbsp;1&amp;nbsp;To&amp;nbsp;Len(sNumber)&amp;nbsp;+&amp;nbsp;6&amp;nbsp;Step&amp;nbsp;6&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ReDim&amp;nbsp;Preserve&amp;nbsp;sRebuild(j)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sRebuild(j)&amp;nbsp;=&amp;nbsp;Mid(sNumber,&amp;nbsp;i,&amp;nbsp;6)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;j&amp;nbsp;=&amp;nbsp;j&amp;nbsp;+&amp;nbsp;1&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Next&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;r&amp;nbsp;=&amp;nbsp;sRebuild(0)&amp;nbsp;Mod&amp;nbsp;modulus&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;For&amp;nbsp;i&amp;nbsp;=&amp;nbsp;0&amp;nbsp;To&amp;nbsp;UBound(sRebuild)&amp;nbsp;-&amp;nbsp;1&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;r&amp;nbsp;=&amp;nbsp;(r&amp;nbsp;&amp;&amp;nbsp;sRebuild(i&amp;nbsp;+&amp;nbsp;1))&amp;nbsp;Mod&amp;nbsp;modulus&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Next&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;largeModulus&amp;nbsp;=&amp;nbsp;r&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;End&amp;nbsp;Function&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;"&gt;The knowledge about the IBAN validation and some code tricks I retrieved from the internet, so it is my turn to to give it back to the community.&lt;/span&gt; &lt;span style="font-family:verdana;"&gt; &lt;/span&gt; &lt;span style="font-family:verdana;"&gt;The functions are also useful in Excel VBA, but not extensively tested. The isIBAN() function is great to use it in your spreadsheet it&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:verdana;"&gt;self, or use it as conditional formatting:&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_k--5h5XK9eM/SGKD7mfyXVI/AAAAAAAAACQ/EVs561ziTmc/s1600-h/conditional+formatting.PNG"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://1.bp.blogspot.com/_k--5h5XK9eM/SGKD7mfyXVI/AAAAAAAAACQ/EVs561ziTmc/s400/conditional+formatting.PNG" alt="" id="BLOGGER_PHOTO_ID_5215876378417847634" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1708518509752812818-8056848830213252777?l=automated-chaos.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://automated-chaos.blogspot.com/feeds/8056848830213252777/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1708518509752812818&amp;postID=8056848830213252777' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/8056848830213252777'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/8056848830213252777'/><link rel='alternate' type='text/html' href='http://automated-chaos.blogspot.com/2008/06/qtp-iban-validation-in-vbscript.html' title='QTP: IBAN validation in VBScript'/><author><name>Bas M. Dam</name><uri>http://www.blogger.com/profile/07594616635957734329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_k--5h5XK9eM/SGKKSBsKuHI/AAAAAAAAACY/xAmkINqunJ0/s72-c/C64_iban.jpeg' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1708518509752812818.post-5677169324379514558</id><published>2008-06-18T18:53:00.008+02:00</published><updated>2008-12-10T21:14:55.939+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='abstract data types'/><category scheme='http://www.blogger.com/atom/ns#' term='QTP'/><category scheme='http://www.blogger.com/atom/ns#' term='classes'/><category scheme='http://www.blogger.com/atom/ns#' term='coding'/><title type='text'>Continued: Creating a Queue data type in QTP</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_k--5h5XK9eM/SFlD-mjYF2I/AAAAAAAAACI/WaI4hEE54Pg/s1600-h/C64andFFdownloadDay.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_k--5h5XK9eM/SFlD-mjYF2I/AAAAAAAAACI/WaI4hEE54Pg/s320/C64andFFdownloadDay.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5213272786437936994" /&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:verdana;"&gt;DONG, Housekeeping message: If you have questions, additional information, an opinion or just something to share, you are very welcome to leave it in the comments. I like to get personal mail too, but as mentioned on &lt;a href="http://www.codinghorror.com/"&gt;coding horrors&lt;/a&gt;: on a blog, &lt;a href="http://www.codinghorror.com/blog/archives/000538.html"&gt;the comments are the best part&lt;/a&gt;. And since I just started, I still need some!&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;In addition to a question I received through email: The class to create a queue on the &lt;a href="http://automated-chaos.blogspot.com/2008/06/abstract-data-types-in-qtp-linked-list.html"&gt;linked list I published Monday&lt;/a&gt;, and how to perform a count on this queue.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Public&amp;nbsp;function&amp;nbsp;queue()&lt;br /&gt;&amp;nbsp;&amp;nbsp;set&amp;nbsp;queue&amp;nbsp;=&amp;nbsp;new&amp;nbsp;clsQueue&lt;br /&gt;End&amp;nbsp;Function&lt;br /&gt;&lt;br /&gt;Class&amp;nbsp;clsQueue&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;Private&amp;nbsp;ll&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;Private&amp;nbsp;Sub&amp;nbsp;Class_Initialize&amp;nbsp;&amp;nbsp;'&amp;nbsp;Setup&amp;nbsp;Initialize&amp;nbsp;event.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;set&amp;nbsp;ll&amp;nbsp;=&amp;nbsp;linkedList&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;Create&amp;nbsp;a&amp;nbsp;linked&amp;nbsp;list&amp;nbsp;instance&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;End&amp;nbsp;Sub&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;Public&amp;nbsp;function&amp;nbsp;pop()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;If&amp;nbsp;ll.count&amp;nbsp;=&amp;nbsp;0&amp;nbsp;Then&amp;nbsp;exit&amp;nbsp;function&amp;nbsp;&amp;nbsp;'&amp;nbsp;No&amp;nbsp;items&amp;nbsp;in&amp;nbsp;the&amp;nbsp;list&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pop&amp;nbsp;=&amp;nbsp;ll.getfirst()&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;Return&amp;nbsp;the&amp;nbsp;last&amp;nbsp;item&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ll.deleteFirst&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;and&amp;nbsp;delete&amp;nbsp;it&lt;br /&gt;&amp;nbsp;&amp;nbsp;End&amp;nbsp;Function&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;Public&amp;nbsp;sub&amp;nbsp;push(element)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ll.add&amp;nbsp;element&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;Add&amp;nbsp;an&amp;nbsp;item&amp;nbsp;to&amp;nbsp;the&amp;nbsp;list&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;End&amp;nbsp;sub&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;Public&amp;nbsp;function&amp;nbsp;peek()&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;peek&amp;nbsp;=&amp;nbsp;ll.getfirst()&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;Peek&amp;nbsp;at&amp;nbsp;the&amp;nbsp;top&amp;nbsp;item&lt;br /&gt;&amp;nbsp;&amp;nbsp;End&amp;nbsp;Function&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;Public&amp;nbsp;property&amp;nbsp;get&amp;nbsp;count()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'return&amp;nbsp;the&amp;nbsp;amount&amp;nbsp;of&amp;nbsp;nodes&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;count&amp;nbsp;=&amp;nbsp;ll.count&lt;br /&gt;&amp;nbsp;&amp;nbsp;End&amp;nbsp;Property&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;br /&gt;End&amp;nbsp;Class&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;"&gt;And this is the part where inheritance and polymorphism is missing. The class looks kind of the same as the stack class, but .getlast() is replaced by .getfirst(). I wish everything in life was this simple… The count property is added, so you can now count the items in the queue. If you want to add a count property to the stack, just do the same in the clsStack.&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1708518509752812818-5677169324379514558?l=automated-chaos.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://automated-chaos.blogspot.com/feeds/5677169324379514558/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1708518509752812818&amp;postID=5677169324379514558' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/5677169324379514558'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/5677169324379514558'/><link rel='alternate' type='text/html' href='http://automated-chaos.blogspot.com/2008/06/continued-creating-queue-data-type-in.html' title='Continued: Creating a Queue data type in QTP'/><author><name>Bas M. Dam</name><uri>http://www.blogger.com/profile/07594616635957734329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_k--5h5XK9eM/SFlD-mjYF2I/AAAAAAAAACI/WaI4hEE54Pg/s72-c/C64andFFdownloadDay.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1708518509752812818.post-2268251924283064685</id><published>2008-06-16T19:09:00.013+02:00</published><updated>2008-12-10T21:14:56.470+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='abstract data types'/><category scheme='http://www.blogger.com/atom/ns#' term='QTP'/><category scheme='http://www.blogger.com/atom/ns#' term='classes'/><category scheme='http://www.blogger.com/atom/ns#' term='coding'/><title type='text'>Abstract data types in QTP: The linked list</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_k--5h5XK9eM/SFamqogRaQI/AAAAAAAAACA/PtLmcWQNFxE/s1600-h/C64_stackUp.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_k--5h5XK9eM/SFamqogRaQI/AAAAAAAAACA/PtLmcWQNFxE/s320/C64_stackUp.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5212536870085421314" /&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:verdana;"&gt;Normally the need for abstract datatypes in Test Automation is not very high. But you will see, just if you don’t have direct access to them, you’ll need them most. Today I had to store some data and it would be nice if I could pop and push it on some stacks. The basis for stacks (and queues) is a linked list. This was a nice Monday morning starter. Linked lists are simple, if you have the right toolset. Unfortunately, QTP and VBScript do not support pointers, so I had to be a little creative. First of all, I created a node class. Each node has a unique index number and a reference to the index numbers of its left and right neighbours. The data is conserved in a public available data element that can contain objects or variants.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;'&amp;nbsp;This&amp;nbsp;is&amp;nbsp;a&amp;nbsp;setup&amp;nbsp;for&amp;nbsp;a&amp;nbsp;linked&amp;nbsp;list.&amp;nbsp;This&amp;nbsp;linked&amp;nbsp;list&amp;nbsp;is&amp;nbsp;the&amp;nbsp;basis&amp;nbsp;for&lt;br /&gt;'&amp;nbsp;queues&amp;nbsp;and&amp;nbsp;stacks.&amp;nbsp;With&amp;nbsp;a&amp;nbsp;little&amp;nbsp;adaptation&amp;nbsp;this&amp;nbsp;can&amp;nbsp;be&amp;nbsp;transformed&amp;nbsp;to&lt;br /&gt;'&amp;nbsp;a&amp;nbsp;binary&amp;nbsp;three&amp;nbsp;or&amp;nbsp;more&amp;nbsp;complex&amp;nbsp;abstract&amp;nbsp;data&amp;nbsp;types.&lt;br /&gt;&lt;br /&gt;Option&amp;nbsp;explicit&lt;br /&gt;&lt;br /&gt;'&amp;nbsp;Initializer&amp;nbsp;for&amp;nbsp;a&amp;nbsp;new&amp;nbsp;listnode.&amp;nbsp;If&amp;nbsp;you&amp;nbsp;keep&amp;nbsp;it&amp;nbsp;private,&amp;nbsp;you&amp;nbsp;don't&amp;nbsp;need&amp;nbsp;this&lt;br /&gt;'&amp;nbsp;caller&amp;nbsp;function&lt;br /&gt;Private&amp;nbsp;function&amp;nbsp;listNode()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Set&amp;nbsp;listNode&amp;nbsp;=&amp;nbsp;new&amp;nbsp;clsListNode&lt;br /&gt;End&amp;nbsp;Function&lt;br /&gt;&lt;br /&gt;'&amp;nbsp;class&amp;nbsp;for&amp;nbsp;a&amp;nbsp;node.&amp;nbsp;The&amp;nbsp;nodeIndex&amp;nbsp;functions&amp;nbsp;as&amp;nbsp;pointerreference&lt;br /&gt;Class&amp;nbsp;clsListNode&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Public&amp;nbsp;data&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'Data,&amp;nbsp;can&amp;nbsp;be&amp;nbsp;a&amp;nbsp;variable&amp;nbsp;or&amp;nbsp;an&amp;nbsp;object&amp;nbsp;(not&amp;nbsp;an&amp;nbsp;array)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Public&amp;nbsp;prevNode&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Public&amp;nbsp;nextNode&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Private&amp;nbsp;nodeIndex&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'Index&amp;nbsp;reference&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;I&amp;nbsp;use&amp;nbsp;a&amp;nbsp;property&amp;nbsp;get&amp;nbsp;to&amp;nbsp;make&amp;nbsp;a&amp;nbsp;defaulter&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Public&amp;nbsp;default&amp;nbsp;property&amp;nbsp;get&amp;nbsp;index()&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;index&amp;nbsp;=&amp;nbsp;nodeIndex&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;End&amp;nbsp;Property&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;and&amp;nbsp;a&amp;nbsp;property&amp;nbsp;let&amp;nbsp;to&amp;nbsp;set&amp;nbsp;a&amp;nbsp;new&amp;nbsp;indexer&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Public&amp;nbsp;property&amp;nbsp;let&amp;nbsp;index(inr)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;nodeIndex&amp;nbsp;=&amp;nbsp;inr&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;End&amp;nbsp;Property&lt;br /&gt;End class&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;To keep track of the nodes, I created an array called collection containing node elements. Collection() is a list of references, but is never referred directly except when we add a new node. If a new node is added, the subscript of collection is incremented to create a new unique reference. Because elements can be added or deleted randomly, do not use collection() and its subscript as a continuous or a chronological list!&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;With add(), we can add an element to the end of the linked list. With getlast() and getfirst() the last and first data elements on the linked list are returned and with deletelast() and deletefirst() the last and first nodes are deleted.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Count() is a helper function, returning the amount of nodes in the list.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;'&amp;nbsp;Make&amp;nbsp;the&amp;nbsp;linked&amp;nbsp;list&amp;nbsp;caller&lt;br /&gt;Public&amp;nbsp;function&amp;nbsp;linkedList()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;set&amp;nbsp;linkedList&amp;nbsp;=&amp;nbsp;new&amp;nbsp;clsLinkedList&lt;br /&gt;End&amp;nbsp;Function&lt;br /&gt;&lt;br /&gt;'&amp;nbsp;The&amp;nbsp;linked&amp;nbsp;list&amp;nbsp;call&lt;br /&gt;Class&amp;nbsp;clsLinkedList&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;collection()&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;a&amp;nbsp;single&amp;nbsp;dimensional&amp;nbsp;array&amp;nbsp;of&amp;nbsp;listNodes&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Private&amp;nbsp;lastItemIndex&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;index&amp;nbsp;of&amp;nbsp;the&amp;nbsp;last&amp;nbsp;item&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Private&amp;nbsp;firstItemIndex&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;index&amp;nbsp;of&amp;nbsp;the&amp;nbsp;first&amp;nbsp;item&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Private&amp;nbsp;indexNumber&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;counter&amp;nbsp;for&amp;nbsp;nodes&amp;nbsp;in&amp;nbsp;the&amp;nbsp;list.&amp;nbsp;Only&amp;nbsp;increment,&amp;nbsp;never&amp;nbsp;decrement!&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Private&amp;nbsp;nodeCount&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;amount&amp;nbsp;of&amp;nbsp;nodes.&amp;nbsp;Ugly&amp;nbsp;but&amp;nbsp;fast.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Private&amp;nbsp;Sub&amp;nbsp;Class_Initialize&amp;nbsp;&amp;nbsp;'&amp;nbsp;Setup&amp;nbsp;Initialize&amp;nbsp;event.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;lastItemIndex&amp;nbsp;=&amp;nbsp;null&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;firstItemIndex&amp;nbsp;=&amp;nbsp;null&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;indexNumber&amp;nbsp;=&amp;nbsp;0&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;nodeCount&amp;nbsp;=&amp;nbsp;0&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;End&amp;nbsp;Sub&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Public&amp;nbsp;sub&amp;nbsp;add(data)&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;add&amp;nbsp;new&amp;nbsp;listNode&amp;nbsp;element&amp;nbsp;to&amp;nbsp;the&amp;nbsp;array&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ReDim&amp;nbsp;preserve&amp;nbsp;collection(indexNumber)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;set&amp;nbsp;collection(indexNumber)&amp;nbsp;=&amp;nbsp;listNode&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;With&amp;nbsp;collection(indexNumber)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;Make&amp;nbsp;the&amp;nbsp;collection&amp;nbsp;compatible&amp;nbsp;for&amp;nbsp;objects&amp;nbsp;as&amp;nbsp;well&amp;nbsp;as&amp;nbsp;normal&amp;nbsp;variables&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;If&amp;nbsp;isObject(data)&amp;nbsp;Then&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;set&amp;nbsp;.data&amp;nbsp;=&amp;nbsp;data&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.data&amp;nbsp;=&amp;nbsp;data&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;End&amp;nbsp;If&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.prevNode&amp;nbsp;=&amp;nbsp;lastItemIndex&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;The&amp;nbsp;previous&amp;nbsp;node&amp;nbsp;of&amp;nbsp;the&amp;nbsp;new&amp;nbsp;node&amp;nbsp;is&amp;nbsp;the&amp;nbsp;current&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;last&amp;nbsp;node&amp;nbsp;reference&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.nextNode&amp;nbsp;=&amp;nbsp;null&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;As&amp;nbsp;it&amp;nbsp;is&amp;nbsp;the&amp;nbsp;last&amp;nbsp;item,&amp;nbsp;there&amp;nbsp;is&amp;nbsp;no&amp;nbsp;reference&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;to&amp;nbsp;the&amp;nbsp;next&amp;nbsp;item&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.index()&amp;nbsp;=&amp;nbsp;indexNumber&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;Set&amp;nbsp;the&amp;nbsp;index&amp;nbsp;of&amp;nbsp;the&amp;nbsp;node&amp;nbsp;to&amp;nbsp;a&amp;nbsp;unique&amp;nbsp;number&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;If&amp;nbsp;not&amp;nbsp;isnull(.prevNode)&amp;nbsp;Then&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;If&amp;nbsp;the&amp;nbsp;newly&amp;nbsp;created&amp;nbsp;node&amp;nbsp;has&amp;nbsp;a&amp;nbsp;left&amp;nbsp;neighbour:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;collection(.prevNode).nextNode&amp;nbsp;=&amp;nbsp;indexNumber&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;the&amp;nbsp;nextnode&amp;nbsp;reference&amp;nbsp;of&amp;nbsp;the&amp;nbsp;left&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;neighbour&amp;nbsp;is&amp;nbsp;the&amp;nbsp;index&amp;nbsp;of&amp;nbsp;the&amp;nbsp;newly&amp;nbsp;created&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;firstItemIndex&amp;nbsp;=&amp;nbsp;.index&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;Else,&amp;nbsp;this&amp;nbsp;is&amp;nbsp;the&amp;nbsp;first&amp;nbsp;node&amp;nbsp;and&amp;nbsp;the&amp;nbsp;first&amp;nbsp;node&amp;nbsp;reference&amp;nbsp;is&amp;nbsp;the&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;end&amp;nbsp;if&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;index&amp;nbsp;of&amp;nbsp;the&amp;nbsp;newly&amp;nbsp;created&amp;nbsp;node&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;end&amp;nbsp;with&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;lastItemIndex&amp;nbsp;=&amp;nbsp;indexNumber&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;As&amp;nbsp;this&amp;nbsp;is&amp;nbsp;the&amp;nbsp;last&amp;nbsp;node,&amp;nbsp;set&amp;nbsp;the&amp;nbsp;reference&amp;nbsp;to&amp;nbsp;this&amp;nbsp;indexnumber&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;indexNumber&amp;nbsp;=&amp;nbsp;indexNumber&amp;nbsp;+&amp;nbsp;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;make&amp;nbsp;a&amp;nbsp;new&amp;nbsp;indexnumber&amp;nbsp;for&amp;nbsp;a&amp;nbsp;unique&amp;nbsp;reference&amp;nbsp;next&amp;nbsp;time&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;nodeCount&amp;nbsp;=&amp;nbsp;nodeCount&amp;nbsp;+&amp;nbsp;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;and&amp;nbsp;increment&amp;nbsp;the&amp;nbsp;nodecounter&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;End&amp;nbsp;sub&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Public&amp;nbsp;property&amp;nbsp;get&amp;nbsp;getlast()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;If&amp;nbsp;nodeCount&amp;nbsp;=&amp;nbsp;0&amp;nbsp;Then&amp;nbsp;exit&amp;nbsp;property&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;No&amp;nbsp;nodes?&amp;nbsp;exit!&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;If&amp;nbsp;isobject(collection(lastItemIndex).data)&amp;nbsp;then&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;Object&amp;nbsp;or&amp;nbsp;variant?&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Set&amp;nbsp;getlast&amp;nbsp;=&amp;nbsp;collection(lastItemIndex).data&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;return&amp;nbsp;object&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;getlast&amp;nbsp;=&amp;nbsp;collection(lastItemIndex).data&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;return&amp;nbsp;variant&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;end&amp;nbsp;if&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;End&amp;nbsp;Property&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Public&amp;nbsp;property&amp;nbsp;get&amp;nbsp;getfirst()&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;If&amp;nbsp;nodeCount&amp;nbsp;=&amp;nbsp;0&amp;nbsp;Then&amp;nbsp;exit&amp;nbsp;property&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;If&amp;nbsp;isobject(collection(firstItemIndex).data)&amp;nbsp;then&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Set&amp;nbsp;getfirst&amp;nbsp;=&amp;nbsp;collection(firstItemIndex).data&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;getfirst&amp;nbsp;=&amp;nbsp;collection(firstItemIndex).data&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;end&amp;nbsp;if&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;End&amp;nbsp;Property&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Public&amp;nbsp;sub&amp;nbsp;deletelast()&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;If&amp;nbsp;nodeCount&amp;nbsp;=&amp;nbsp;0&amp;nbsp;Then&amp;nbsp;exit&amp;nbsp;sub&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'Exit&amp;nbsp;on&amp;nbsp;no&amp;nbsp;nodes&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Dim&amp;nbsp;tempLastIndex&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;tempLastIndex&amp;nbsp;=&amp;nbsp;lastItemIndex&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'Make&amp;nbsp;a&amp;nbsp;temp&amp;nbsp;for&amp;nbsp;the&amp;nbsp;last&amp;nbsp;index&amp;nbsp;number&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;Check&amp;nbsp;if&amp;nbsp;there&amp;nbsp;is&amp;nbsp;a&amp;nbsp;previous&amp;nbsp;node&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;If&amp;nbsp;not&amp;nbsp;isnull(collection(lastItemIndex).prevNode)&amp;nbsp;&amp;nbsp;Then&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;Set&amp;nbsp;the&amp;nbsp;reference&amp;nbsp;for&amp;nbsp;the&amp;nbsp;last&amp;nbsp;item&amp;nbsp;to&amp;nbsp;the&amp;nbsp;index&amp;nbsp;of&amp;nbsp;the&amp;nbsp;left&amp;nbsp;neighbour&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;lastItemIndex&amp;nbsp;=&amp;nbsp;collection(collection(lastItemIndex).prevNode).index&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;Set&amp;nbsp;the&amp;nbsp;reference&amp;nbsp;for&amp;nbsp;the&amp;nbsp;next&amp;nbsp;node&amp;nbsp;of&amp;nbsp;the&amp;nbsp;left&amp;nbsp;neighbour&amp;nbsp;to&amp;nbsp;null&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;collection(lastItemIndex).nextNode&amp;nbsp;=&amp;nbsp;null&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;End&amp;nbsp;If&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;destroy&amp;nbsp;the&amp;nbsp;node&amp;nbsp;element&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Set&amp;nbsp;collection(tempLastIndex)&amp;nbsp;=&amp;nbsp;nothing&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;decrement&amp;nbsp;the&amp;nbsp;node&amp;nbsp;counter&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;nodeCount&amp;nbsp;=&amp;nbsp;nodeCount&amp;nbsp;-&amp;nbsp;1&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;End&amp;nbsp;Sub&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Public&amp;nbsp;sub&amp;nbsp;deletefirst()&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;If&amp;nbsp;nodeCount&amp;nbsp;=&amp;nbsp;0&amp;nbsp;Then&amp;nbsp;exit&amp;nbsp;sub&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Dim&amp;nbsp;tempFirstIndex&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;tempFirstIndex&amp;nbsp;=&amp;nbsp;firstItemIndex&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;Check&amp;nbsp;if&amp;nbsp;there&amp;nbsp;is&amp;nbsp;a&amp;nbsp;next&amp;nbsp;node&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;If&amp;nbsp;not&amp;nbsp;isnull(collection(firstItemIndex).nextNode)&amp;nbsp;&amp;nbsp;Then&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;Set&amp;nbsp;the&amp;nbsp;reference&amp;nbsp;for&amp;nbsp;the&amp;nbsp;first&amp;nbsp;item&amp;nbsp;to&amp;nbsp;the&amp;nbsp;index&amp;nbsp;of&amp;nbsp;the&amp;nbsp;right&amp;nbsp;neighbour&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;firstItemIndex&amp;nbsp;=&amp;nbsp;collection(collection(firstItemIndex).nextNode).index&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;Set&amp;nbsp;the&amp;nbsp;reference&amp;nbsp;for&amp;nbsp;the&amp;nbsp;previous&amp;nbsp;node&amp;nbsp;of&amp;nbsp;the&amp;nbsp;right&amp;nbsp;neighbour&amp;nbsp;to&amp;nbsp;null&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;collection(firstItemIndex).prevNode&amp;nbsp;=&amp;nbsp;null&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;End&amp;nbsp;If&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Set&amp;nbsp;collection(tempFirstIndex)&amp;nbsp;=&amp;nbsp;nothing&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;nodeCount&amp;nbsp;=&amp;nbsp;nodeCount&amp;nbsp;-&amp;nbsp;1&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;End&amp;nbsp;Sub&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Public&amp;nbsp;property&amp;nbsp;get&amp;nbsp;count()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'return&amp;nbsp;the&amp;nbsp;amount&amp;nbsp;of&amp;nbsp;nodes&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;count&amp;nbsp;=&amp;nbsp;nodeCount&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;End&amp;nbsp;Property&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;end&amp;nbsp;class&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:verdana;"&gt;Some test statements to show how it works::&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;Dim&amp;nbsp;ll,&amp;nbsp;mc&lt;br /&gt;Set&amp;nbsp;ll&amp;nbsp;=&amp;nbsp;linkedList&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ll.add&amp;nbsp;"first"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ll.add&amp;nbsp;"second"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ll.add&amp;nbsp;"third"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ll.add&amp;nbsp;"fourth"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ll.add&amp;nbsp;"fifth"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;msgbox&amp;nbsp;ll.getFirst()&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;&gt;first&lt;br /&gt;msgbox&amp;nbsp;ll.getLast()&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;&gt;fifth&lt;br /&gt;&lt;br /&gt;'&amp;nbsp;Delete&amp;nbsp;the&amp;nbsp;first&amp;nbsp;item&lt;br /&gt;ll.deletefirst&lt;br /&gt;msgbox&amp;nbsp;ll.getFirst()&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;&gt;second&lt;br /&gt;&lt;br /&gt;msgbox&amp;nbsp;ll.count&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;&gt;4&lt;br /&gt;&lt;br /&gt;'&amp;nbsp;Delete&amp;nbsp;the&amp;nbsp;last&amp;nbsp;two&amp;nbsp;items&lt;br /&gt;ll.deletelast&lt;br /&gt;ll.deletelast&lt;br /&gt;msgbox&amp;nbsp;ll.getLast()&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;&gt;third&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:verdana;"&gt;The linked list class makes it very easy to create stacks and queues. Here is an example of how to create a stack: &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;Public&amp;nbsp;function&amp;nbsp;stack()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;set&amp;nbsp;stack&amp;nbsp;=&amp;nbsp;new&amp;nbsp;clsStack&lt;br /&gt;End&amp;nbsp;Function&lt;br /&gt;&lt;br /&gt;Class&amp;nbsp;clsStack&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Private&amp;nbsp;ll&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Private&amp;nbsp;Sub&amp;nbsp;Class_Initialize&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;Setup&amp;nbsp;Initialize&amp;nbsp;event.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;set&amp;nbsp;ll&amp;nbsp;=&amp;nbsp;linkedList&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;Create&amp;nbsp;a&amp;nbsp;linked&amp;nbsp;list&amp;nbsp;instance&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;End&amp;nbsp;Sub&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Public&amp;nbsp;function&amp;nbsp;pop()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;If&amp;nbsp;ll.count&amp;nbsp;=&amp;nbsp;0&amp;nbsp;Then&amp;nbsp;exit&amp;nbsp;function&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;No&amp;nbsp;items&amp;nbsp;in&amp;nbsp;the&amp;nbsp;list&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pop&amp;nbsp;=&amp;nbsp;ll.getlast()&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;Return&amp;nbsp;the&amp;nbsp;last&amp;nbsp;item&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ll.deleteLast&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;and&amp;nbsp;delete&amp;nbsp;it&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;End&amp;nbsp;Function&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Public&amp;nbsp;sub&amp;nbsp;push(element)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ll.add&amp;nbsp;element&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;Add&amp;nbsp;an&amp;nbsp;item&amp;nbsp;to&amp;nbsp;the&amp;nbsp;list&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;End&amp;nbsp;sub&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Public&amp;nbsp;function&amp;nbsp;peek()&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;peek&amp;nbsp;=&amp;nbsp;ll.getlast()&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;Peek&amp;nbsp;at&amp;nbsp;the&amp;nbsp;top&amp;nbsp;item&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;End&amp;nbsp;Function&lt;br /&gt;&lt;br /&gt;End&amp;nbsp;Class&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:verdana;"&gt;And some sample code for a little demonstration:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;Dim&amp;nbsp;myStack&lt;br /&gt;set&amp;nbsp;myStack&amp;nbsp;=&amp;nbsp;stack&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;Set&amp;nbsp;as&amp;nbsp;new&amp;nbsp;stack&lt;br /&gt;&lt;br /&gt;myStack.push&amp;nbsp;"item1"&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;Add&amp;nbsp;some&amp;nbsp;items&lt;br /&gt;myStack.push&amp;nbsp;"item2"&lt;br /&gt;myStack.push&amp;nbsp;"item3"&lt;br /&gt;&lt;br /&gt;msgbox&amp;nbsp;myStack.pop()&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;&gt;item3&lt;br /&gt;msgbox&amp;nbsp;myStack.peek()&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;&gt;item2&lt;br /&gt;msgbox&amp;nbsp;myStack.pop()&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;'&amp;nbsp;&gt;item2&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:verdana;"&gt;The thing that is missing for generic use is an insertbefore() and an insertafter() method on the linked list. But to implement this, you'll need a virtual reference table that maps the collection() array index to a chronologic ánd continuous index. Another way to do this is a looping mechanism where you can walk through the elements with a getnext() or getprevious() method.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;For now, the stack and queue functionality is sufficient for my needs.&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1708518509752812818-2268251924283064685?l=automated-chaos.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://automated-chaos.blogspot.com/feeds/2268251924283064685/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1708518509752812818&amp;postID=2268251924283064685' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/2268251924283064685'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/2268251924283064685'/><link rel='alternate' type='text/html' href='http://automated-chaos.blogspot.com/2008/06/abstract-data-types-in-qtp-linked-list.html' title='Abstract data types in QTP: The linked list'/><author><name>Bas M. Dam</name><uri>http://www.blogger.com/profile/07594616635957734329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_k--5h5XK9eM/SFamqogRaQI/AAAAAAAAACA/PtLmcWQNFxE/s72-c/C64_stackUp.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1708518509752812818.post-1484500349688797585</id><published>2008-06-12T19:59:00.005+02:00</published><updated>2008-12-10T21:14:58.084+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tricks'/><category scheme='http://www.blogger.com/atom/ns#' term='QTP'/><category scheme='http://www.blogger.com/atom/ns#' term='code optimization'/><category scheme='http://www.blogger.com/atom/ns#' term='coding'/><title type='text'>Option Explicit and other QTP curiosities</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_k--5h5XK9eM/SFFrCSGBW-I/AAAAAAAAAB0/FekNHQqEtC0/s1600-h/C64Assembly.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://2.bp.blogspot.com/_k--5h5XK9eM/SFFrCSGBW-I/AAAAAAAAAB0/FekNHQqEtC0/s320/C64Assembly.jpg" alt="" id="BLOGGER_PHOTO_ID_5211063930805378018" border="0" /&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:verdana;"&gt;I like variable declaration and strong type casting. It makes sense, because it makes sense in assembly. And it prevents me from making mistakes in variable names. QTP offers variable declaration with the command "option explicit". This works just the same as in VBA or VB, but... you need to be consequent. Every action script, function library or external vbs file needs an option explicit command or else it won't work. You thought you didn't need it in that tiny class file where mistakes are not possible? You thought wrong. Ignoring one option explicit, makes all other option explicits obsolete and your scripts will be interpreted without the need for variable declaration.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;By the way, undeclared variable detection only works during runtime. There is no pre-compile option as in VB or VBA, so it is good old trial and error when you want to debug your script on undeclared variables.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;"Randomize"  has sort of the same behavior: Don't put it in a header script or such kind, but put it in the library where you use the rnd function. If you use rnd in multiple libraries, you'll have to put Randomize in each of them, otherwise you are stuck with the same 'random' numbers each time you run the script.&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1708518509752812818-1484500349688797585?l=automated-chaos.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://automated-chaos.blogspot.com/feeds/1484500349688797585/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1708518509752812818&amp;postID=1484500349688797585' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/1484500349688797585'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/1484500349688797585'/><link rel='alternate' type='text/html' href='http://automated-chaos.blogspot.com/2008/06/option-explicit-and-other-qtp.html' title='Option Explicit and other QTP curiosities'/><author><name>Bas M. Dam</name><uri>http://www.blogger.com/profile/07594616635957734329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_k--5h5XK9eM/SFFrCSGBW-I/AAAAAAAAAB0/FekNHQqEtC0/s72-c/C64Assembly.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1708518509752812818.post-7860643812360120193</id><published>2008-06-11T18:56:00.004+02:00</published><updated>2008-12-10T21:14:58.354+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tricks'/><category scheme='http://www.blogger.com/atom/ns#' term='QTP'/><category scheme='http://www.blogger.com/atom/ns#' term='coding'/><title type='text'>object.exist() in QTP needs company</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_k--5h5XK9eM/SFAMBnIxvFI/AAAAAAAAABo/60bpwUshwTA/s1600-h/companyC64.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_k--5h5XK9eM/SFAMBnIxvFI/AAAAAAAAABo/60bpwUshwTA/s320/companyC64.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5210677990692863058" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: verdana;"&gt;It took me some time last week to figure out that the&lt;span style="font-family: courier new;"&gt; .exist() &lt;/span&gt;method does not work on a stand alone base. It passes a return value, and you need to do something with that value. For normal usage of &lt;span style="font-family: courier new;"&gt;.exist() &lt;/span&gt;this is obvious:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;If QTPobject.exist Then msgbox "The object is present!"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;But as a WinRunner user (did I mention that before?) I use the appearance of objects as an intrinsic  synchronization method like:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;btn_click("Open New Window");&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;win_exists("New Window", wait_normal);        # synchronize 'wait_normal' seconds&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;set_window("New Window", 1);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;...&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Since I did a lot with webtesting, I didn't like to use the &lt;span style="font-family: courier new;"&gt;set_window() &lt;/span&gt;function before the frame was actually present, because it could cause a IE crash. That is why I used the &lt;span style="font-family: courier new;"&gt;win_exists()&lt;/span&gt; function.&lt;br /&gt;&lt;br /&gt;But now in QTP. When you use &lt;span style="font-family: courier new;"&gt;.exist() &lt;/span&gt;with QTP objects in this way, it won't work:&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;QTPobject.exist&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;or&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;call QTPobject.exist&lt;/span&gt;&lt;br /&gt;results in an 'Method is not valid for this object' error.&lt;br /&gt;&lt;br /&gt;The only way to let it work, is passing the outcome to a dummy variable:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;dummy = QTPobject.exist&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This sometimes exotic behavior of QTP can be frustrating.&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1708518509752812818-7860643812360120193?l=automated-chaos.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://automated-chaos.blogspot.com/feeds/7860643812360120193/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1708518509752812818&amp;postID=7860643812360120193' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/7860643812360120193'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/7860643812360120193'/><link rel='alternate' type='text/html' href='http://automated-chaos.blogspot.com/2008/06/objectexist-in-qtp-needs-company.html' title='object.exist() in QTP needs company'/><author><name>Bas M. Dam</name><uri>http://www.blogger.com/profile/07594616635957734329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_k--5h5XK9eM/SFAMBnIxvFI/AAAAAAAAABo/60bpwUshwTA/s72-c/companyC64.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1708518509752812818.post-6664535401936963774</id><published>2008-06-06T19:20:00.003+02:00</published><updated>2008-06-12T20:31:39.757+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='automated testing'/><category scheme='http://www.blogger.com/atom/ns#' term='QTP'/><title type='text'>QTP and the curse of the interview questions</title><content type='html'>&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:verdana;"&gt;Quick Test Professional is getting popular. It &lt;a href="http://www.googlebattle.com/index.php?domain=winrunner&amp;amp;domain2=qtp&amp;amp;submit=Go%21"&gt;wins&lt;/a&gt; easily from good-old-and-soon-to-be-disposed WinRunner. &lt;/span&gt;&lt;span style="font-family:verdana;"&gt;Because QTP is relatively new, all over the internet the knowledge bases are still building up. That is good thing. Not a good thing in my opinion is the way people are trying to get a job. Just do a search on “&lt;a href="http://www.google.com/search?hl=en&amp;amp;q=qtp+interview+questions"&gt;QTP interview question&lt;/a&gt;” or better “&lt;a href="http://www.google.com/search?hl=en&amp;amp;q=qtp+interview+answers"&gt;QTP interview answers&lt;/a&gt;” and see for yourself; there seems to be a large market for publishing answers on interview questions. And this is something that scares me.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;When a project wants to start automating their tests, it is automatically a shift in the test process. Testers have to be stricter in defining and formatting their data, business analysts do have to make clear requirements and the development team has to cope with standards. None of them is a bad thing, unless you don’t want to improve your test and development process of course.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Most of the time there is no automated test available yet and the project is searching for a specialist who can design and implement the automated test. When the decision for test automation is made, the business puts lots of assets on the automated tests that have to be developed. Besides the significant costs, the assets also include the change and implementation of the architecture, test framework, risk model, the fitting on the manual tests and the test process. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;And then, the interviews. The interviews with potential test automation specialists are most of the time performed by test managers, project leads and colleague testers, none of them very experienced in test automation. The most technical guy of them probably had played with the test automation software a bit, and he is the likely one to ask some technical questions.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;But how can you make a difference between candidate A and candidate B if the answers to those questions can be learned by head? Or even worse, what if you only have candidates that have their knowledge from the internet? You pick the best one and you are satisfied with that, but it is like choosing between a blind carpenter and one without hands. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Right now, there are more people who like to &lt;span style="font-style: italic;"&gt;work&lt;/span&gt; with WinRunner than to actually &lt;a style="font-style: italic;" href="http://www.googlebattle.com/index.php?domain=winrunner+interview+questions&amp;amp;domain2=learn+winrunner&amp;amp;submit=Go%21"&gt;learn&lt;/a&gt; it. Soon enough, QTP will end up with the same statistics. That is not a good sign for the automated test business in general. Inexperienced people on projects claiming the contrary might result in failures. Project managers don’t like failures and when test automation gets associated with failure, you'll get a hard time convincing them of the opposite.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Certification is a hot topic right now. I am not a big proponent of pointlessly requiring a certificate for every tool you want to use. On the other site, it sifts the wheat from the chaff at forehand and it gives an instrument to projects, inexperienced with test automation, letting them easily select the experts from an applicant pool.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1708518509752812818-6664535401936963774?l=automated-chaos.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://automated-chaos.blogspot.com/feeds/6664535401936963774/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1708518509752812818&amp;postID=6664535401936963774' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/6664535401936963774'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/6664535401936963774'/><link rel='alternate' type='text/html' href='http://automated-chaos.blogspot.com/2008/06/qtp-and-curse-of-interview-questions.html' title='QTP and the curse of the interview questions'/><author><name>Bas M. Dam</name><uri>http://www.blogger.com/profile/07594616635957734329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1708518509752812818.post-7628746108191716726</id><published>2008-06-05T20:37:00.005+02:00</published><updated>2008-12-10T21:14:59.235+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tricks'/><category scheme='http://www.blogger.com/atom/ns#' term='automated testing'/><category scheme='http://www.blogger.com/atom/ns#' term='external functions'/><category scheme='http://www.blogger.com/atom/ns#' term='regular expressions'/><category scheme='http://www.blogger.com/atom/ns#' term='winrunner'/><category scheme='http://www.blogger.com/atom/ns#' term='coding'/><title type='text'>Real Regular Expressions in WinRunner</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_k--5h5XK9eM/SEhBut5dB0I/AAAAAAAAABg/mwDAOa6iNbo/s1600-h/cleverensmartC64.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_k--5h5XK9eM/SEhBut5dB0I/AAAAAAAAABg/mwDAOa6iNbo/s320/cleverensmartC64.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5208485239904339778" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: verdana;"&gt;Automated testing without regular expressions is almost unthinkable nowadays. But there was a time, almost nobody knew what regex's were. Only a handful of developers and they were all working on Unix.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;WinRunner started with support of regex's  years ago, because it seemed to be handy for testers. Unfortunately  they did it only with their own set of limited meta characters. You can use the . for any character, the * for zero to unlimited of the previous character, the square brackets [ ] for ranges or included characters and that was it.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Probably they thought that the full set of regular expression characters was overkill for non technical users like testers, and they could not know that regular expressions would become so regular.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;I presume that for compatibility purposes Mercury never upgraded their set of regular expressions, but it is a real handicap when you are deep into the test automation.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;After a bit of searching, I found this site on the internet: &lt;/span&gt;&lt;a style="font-family: verdana;" href="http://members.aol.com/TeaAndBikkie/re_func.html"&gt;Misha's regex&lt;/a&gt;&lt;span style="font-family: verdana;"&gt;. Misha did a great job, porting C++ regular expressions to a dynamic library that can be loaded into WinRunner. Also, he provides some WinRunner functions to give you a kick start when you want to work with it.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;As far as I know, this is the only ready to use solution for WinRunner to implement full regular expressions. And even better, you can now use "label_like" and "id_like" as attributes in object recognition.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;The only thing I did was writing to simple functions to do a simple match:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;public function re_match_simple(in orig_str, in pattern) {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;auto outPos, outLen, outDetail;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;    &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return re_match(orig_str, pattern, outPos, outLen, outDetail);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;} &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;public function re_search_simple(in orig_str, in pattern) {&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;auto outPos, outLen, outDetail;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;    &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (re_search(orig_str, pattern, outPos, outLen, outDetail)) &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return outPos+1;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;# +1, otherwise 0 (=FALSE) will be returned if found on first position&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;        &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return FALSE;    &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;This allows me to do quick checks like&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;if (!re_match_simple(outDate, "^\d{1,2}-[JFMASOND][aepuco][nbrylgptvc]-(19|20)\d\d$")&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;myReport("Date format for '"outDate"' is not according standard: dd-Mmm-yyyy", eCHECK);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;or&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;customerId = substr(fullText, re_search_simple(fullText, "\d{8}"), 8);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Even the test analists are working with regular expressions. (on that particular project we worked with separated roles: testautomation and testanalysis). The only thing they had to do was flag a string with an exclamation mark (!) in front and it was checked as an regular expression. The exlamation mark for obvious reasons.&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1708518509752812818-7628746108191716726?l=automated-chaos.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://automated-chaos.blogspot.com/feeds/7628746108191716726/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1708518509752812818&amp;postID=7628746108191716726' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/7628746108191716726'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/7628746108191716726'/><link rel='alternate' type='text/html' href='http://automated-chaos.blogspot.com/2008/06/real-regular-expressions-in-winrunner.html' title='Real Regular Expressions in WinRunner'/><author><name>Bas M. Dam</name><uri>http://www.blogger.com/profile/07594616635957734329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_k--5h5XK9eM/SEhBut5dB0I/AAAAAAAAABg/mwDAOa6iNbo/s72-c/cleverensmartC64.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1708518509752812818.post-4158684339789122959</id><published>2008-06-04T21:41:00.011+02:00</published><updated>2008-12-10T21:14:59.578+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='transition'/><category scheme='http://www.blogger.com/atom/ns#' term='QTP'/><category scheme='http://www.blogger.com/atom/ns#' term='object repository'/><category scheme='http://www.blogger.com/atom/ns#' term='pitfalls'/><category scheme='http://www.blogger.com/atom/ns#' term='winrunner'/><category scheme='http://www.blogger.com/atom/ns#' term='mercury'/><title type='text'>QTP pitfalls for WinRunner users (Part II)</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_k--5h5XK9eM/SEcECb6EMBI/AAAAAAAAABY/r2-nbgVOxXY/s1600-h/pitfallmini2.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://3.bp.blogspot.com/_k--5h5XK9eM/SEcECb6EMBI/AAAAAAAAABY/r2-nbgVOxXY/s320/pitfallmini2.jpg" alt="" id="BLOGGER_PHOTO_ID_5208135933974818834" border="0" /&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:verdana;"&gt;&lt;br /&gt;Today was another day of fiddling around with QTP. The VBScript language of QTP is still a bit new to me and I stumbled into some neatly disguised traps:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;font-family:verdana;font-size:85%;"  &gt;1. The &lt;span style="font-family:courier new;"&gt;.exist(&lt;/span&gt;&lt;span style="font-style: italic;font-family:courier new;" &gt;n&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;)&lt;/span&gt; method is in seconds&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Normally I use the &lt;span style="font-family:courier new;"&gt;.exist() &lt;/span&gt;method for synchronization, but today I used it for checking if the right finalise page was reached or that I had to cope with an data validation error somewhere. I do not bother test objects, because at this moment I am not testing, but just doing an automated data entry project with some complex datamodels. (This is where the classes are hopping in I mentioned before).&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;To test my code, I started my QTP script and went for my lunch. When I got back, only one set of data was entered and the screen was synchronizing on a page. And synchronizing. And synchronizing.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;After pressing the stop button and debugging my code, I found out that the wait time in &lt;span style="font-family:courier new;"&gt;exist(&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-style: italic;font-family:courier new;font-size:85%;"  &gt;n&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:verdana;"&gt;&lt;span style="font-family:courier new;"&gt;) &lt;/span&gt;is expected in seconds,&lt;/span&gt;&lt;/span&gt;&lt;span style="font-weight: bold;font-family:verdana;font-size:85%;"  &gt; &lt;/span&gt;&lt;span style="font-style: italic;font-family:verdana;font-size:85%;"  &gt;while the help file mentions milliseconds!&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:verdana;"&gt;My script was waiting for a never appearing page for 10.000 seconds instead of 10.000 milliseconds.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Not very uncommon for the WinRunner user by the way (&lt;span style="font-family:courier new;"&gt;obj_exists() &lt;/span&gt;and &lt;span style="font-family:courier new;"&gt;win_exists()&lt;/span&gt; works almost the same), only misleading because of incorrect information the help file.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;font-family:verdana;font-size:85%;"  &gt;2. Location is optional in object identification&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:verdana;"&gt;When there are multiple object in your AUT that match the same description in the object repository, QTP just picks the first one when the ordinal properties are set to 'none'.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;And this property is always set to none whenever you learned the object while it was unique on the screen.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;In WinRunner, you used to get the error message E_NOT_UNIQUE, but QTP is figuring it out all by itself, even with Smart Identification switched off. Something to keep in mind.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;font-family:verdana;font-size:85%;"  &gt;3. &lt;span style="font-family:courier new;"&gt;Eval() &lt;/span&gt;is not exactly &lt;span style="font-family:courier new;"&gt;eval();&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:verdana;"&gt;&lt;span style="font-family:courier new;"&gt;Eval()&lt;/span&gt; in QTP is used for comparison, while &lt;span style="font-family:courier new;"&gt;Execute()&lt;/span&gt; is used for assignment:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;a = 2&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;msgbox eval("a = 2")            ' displays 'True'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;msgbox a                                            ' displays '2'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;msgbox execute("a = 3")        ' displays nothing, a is set to 3&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;msgbox a                                            ' displays '3'&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;font-family:verdana;font-size:85%;"  &gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:verdana;"&gt;Keep this in mind if you used the &lt;span style="font-family:courier new;"&gt;eval()&lt;/span&gt; function in WinRunner for assignment of virtual variables. It won't work in QTP and you have to use &lt;span style="font-family:courier new;"&gt;execute().&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-weight: bold;font-family:verdana;font-size:85%;"  &gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;font-family:verdana;font-size:85%;"  &gt;4. There is no fast way to export the object repository to plain text&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:verdana;"&gt;Unlike WinRunner, where the GUI map was just a plain text file, it is not possible to easily export (and manipulate) the object repository. It is possible though, but you'll have to do it through COM automation on the QTP application. I tried it today, but I failed miserably because I could not access the ActiveX object (probably not enough authorization on my workstation).&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;However, if I get it working, I will post the code on Automated Chaos.&lt;/span&gt;&lt;/span&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="font-style: italic;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1708518509752812818-4158684339789122959?l=automated-chaos.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://automated-chaos.blogspot.com/feeds/4158684339789122959/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1708518509752812818&amp;postID=4158684339789122959' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/4158684339789122959'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/4158684339789122959'/><link rel='alternate' type='text/html' href='http://automated-chaos.blogspot.com/2008/06/qtp-pitfalls-for-winrunner-users.html' title='QTP pitfalls for WinRunner users (Part II)'/><author><name>Bas M. Dam</name><uri>http://www.blogger.com/profile/07594616635957734329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_k--5h5XK9eM/SEcECb6EMBI/AAAAAAAAABY/r2-nbgVOxXY/s72-c/pitfallmini2.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1708518509752812818.post-2629916553130754434</id><published>2008-06-03T19:43:00.009+02:00</published><updated>2008-12-10T21:14:59.829+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='automated testing'/><category scheme='http://www.blogger.com/atom/ns#' term='desktop extension'/><category scheme='http://www.blogger.com/atom/ns#' term='API'/><category scheme='http://www.blogger.com/atom/ns#' term='utilities'/><category scheme='http://www.blogger.com/atom/ns#' term='text editing'/><category scheme='http://www.blogger.com/atom/ns#' term='screenprinting'/><category scheme='http://www.blogger.com/atom/ns#' term='scheduling'/><title type='text'>My Top 5 Ultimate Utilities for Testing</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_k--5h5XK9eM/SEWj076EMAI/AAAAAAAAABM/bbdFE6juTRk/s1600-h/koalapainter.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_k--5h5XK9eM/SEWj076EMAI/AAAAAAAAABM/bbdFE6juTRk/s320/koalapainter.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5207748673953607682" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:verdana;"&gt;This is my list of top 5 utilities I use for (automated) testing. I use them as helper programs in the  (automated) test process, so this is not a list stating automated test tools, bug loggers etc. Every header is a link to the location where you can find the application.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a style="font-family: verdana;" href="http://www.activevb.de/rubriken/apiviewer/index-apiviewereng.html"&gt;5. API Viewer&lt;/a&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;View all useable functions and constants from all common Window API's and auto generate C/VB code for it.&lt;/span&gt;&lt;br /&gt;&lt;a style="font-family: verdana;" href="http://sourceforge.net/project/showfiles.php?group_id=77456"&gt;&lt;br /&gt;4. Pycron&lt;/a&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Your own cron tab under Windows, with GUI for editing events. You can run this as command line or as service. Stable, small and can run stand alone.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a style="font-family: verdana;" href="http://portableapps.com/apps/development/notepadpp_portable"&gt;3. Notepad++ Portable&lt;/a&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;A notepad with many options. Simular to text editors as ultraedit except this one is free and can run stand alone (if you choose the portable version).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a style="font-family: verdana;" href="http://sourceforge.net/project/showfiles.php?group_id=59275"&gt;2. Synergy&lt;/a&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Very useful when having multiple PCs with multiple monitors, but when you only want to use 1 keyboard/mouse combination. Mouse movement works just as you would expect from a dual/triple monitor setup, only you cannot drag your windows to the other screen (because it is a physical other machine). However the application manages to get copy pasting of text working most of the time.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a style="font-family: verdana;" href="http://www.gadwin.com/download/"&gt;1. Gadwin Printscreen&lt;/a&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;A customizable screen dump tool with one major advantage above lots of others: It can be called by the Command line. This gives it a great usage during automated testing.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Contains all features you'll expect in an ultimate tool: jpg, png, bmp and gif formats, custom filename, incremential filename, silence mode etc.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;This application works stand alone (once unpacked, there is no installation needed on specific workstations, just run the executable).&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1708518509752812818-2629916553130754434?l=automated-chaos.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://automated-chaos.blogspot.com/feeds/2629916553130754434/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1708518509752812818&amp;postID=2629916553130754434' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/2629916553130754434'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/2629916553130754434'/><link rel='alternate' type='text/html' href='http://automated-chaos.blogspot.com/2008/06/my-top-5-ultimate-utilities.html' title='My Top 5 Ultimate Utilities for Testing'/><author><name>Bas M. Dam</name><uri>http://www.blogger.com/profile/07594616635957734329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_k--5h5XK9eM/SEWj076EMAI/AAAAAAAAABM/bbdFE6juTRk/s72-c/koalapainter.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1708518509752812818.post-5728524553423632274</id><published>2008-06-03T08:38:00.007+02:00</published><updated>2008-12-10T21:15:00.982+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tricks'/><category scheme='http://www.blogger.com/atom/ns#' term='external functions'/><category scheme='http://www.blogger.com/atom/ns#' term='code optimization'/><category scheme='http://www.blogger.com/atom/ns#' term='function calls'/><category scheme='http://www.blogger.com/atom/ns#' term='winrunner'/><category scheme='http://www.blogger.com/atom/ns#' term='mercury'/><title type='text'>Lowlevel Code Optimization in WinRunner</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_k--5h5XK9eM/SEUuZr6EL_I/AAAAAAAAABE/31zvGzZ-jWw/s1600-h/power.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_k--5h5XK9eM/SEUuZr6EL_I/AAAAAAAAABE/31zvGzZ-jWw/s320/power.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5207619562941722610" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: verdana;"&gt;At some moment in your automated test project you enter the phase you are questioning yourself: "Weren't we automating the tests because it is fast? Why are my tests running so slow!?!". Then it is time to review your code and to optimize it a bit.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;In this post, I want to discuss low level optimization. As WinRunner does not have a smart compiler (it is more an interpreted language then a compiled one), we have to do all optimizations by ourself.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; font-family: verdana;"&gt;1. Order of function calls in a condition&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;When you use and and or constructs in conditions ('if' statements for example), you have to think about the order:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Let's say, we have two checks, a time consuming (&lt;span style="font-family: courier new;"&gt;fncSlowCheck&lt;/span&gt;) and a fast one (&lt;span style="font-family: courier new;"&gt;fncFastCheck&lt;/span&gt;). &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;When you use an AND or an OR construct, you need to put the fastest compare first:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;i&lt;span style="font-family: courier new;"&gt;f (fncFastCheck() == E_OK &amp;amp;&amp;amp; fncSlowCheck() == E_OK) { ... }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;if (fncFastCheck() == E_OK || fncSlowCheck() == E_OK) { ... }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;WinRunner will first evaluate the fast function. When this evaluates to false, the second function will not be called in case of the AND construction, because the total if statement can never become TRUE, and the if statement is stepped over.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;With the OR, it is just the other way around. When the first function evaluates to TRUE, the second function will not be called.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;This behavior is called lazy evaluation and is something you have to keep in mind when you use functions in conditional statements that can impact the application under test.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;if (edit_set(myEdit1, "foo") != E_OK &amp;amp;&amp;amp; edit_set(myEdit2, "bar") != E_OK) {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;write2report("Something went wrong setting myEdit1 and/or myEdit2", ERROR)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Besides this is a crappy way of reporting, the second edit will never be set as soon the first &lt;span style="font-family: courier new;"&gt;edit_set() &lt;/span&gt;evaluates to an error.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; font-family: verdana;"&gt;2. Use switch / case constructs. They are fast!&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;The reason why switch / case are fast is because &lt;span style="font-family: courier new;"&gt;jmp&lt;/span&gt; (jump) commands in assembly are faster than &lt;span style="font-family: courier new;"&gt;cmp&lt;/span&gt; (compare) commands used with each loop iteration. Combined with the so called "fall through" mechanism, they cannot be beaten by loops. For a detailed article, see &lt;/span&gt;&lt;a style="font-family: verdana;" href="http://en.wikipedia.org/wiki/Duff%27s_device"&gt;Duff's device on wikipedia&lt;/a&gt;&lt;span style="font-family: verdana;"&gt;.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; font-family: verdana;"&gt;3. ++i is faster than i++&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: verdana;"&gt;Make it a good habit to use &lt;span style="font-family: courier new;"&gt;++{variable}&lt;/span&gt; in your &lt;span style="font-family: courier new;"&gt;for&lt;/span&gt; constructs:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;for (i = 0 ; i &lt; 100 ; ++i)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;I absolutely noticed the difference since I had some large multi dimensional arrays I had to iterate through. &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;One note: Keep in mind the order of handling of the incrementation. Do not blindly search and replace all &lt;span style="font-family: courier new;"&gt;{variable}++&lt;/span&gt; with &lt;span style="font-family: courier new;"&gt;++{variable}&lt;/span&gt;, this will mess up your test.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; font-family: verdana;"&gt;4. Calls to external functions can be slow&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; font-family: verdana;"&gt;&lt;/span&gt;&lt;span style="font-family: verdana;"&gt;When you use external functions in time critical processes, it is a good habit to check the performance of these functions. Once, I had external &lt;span style="font-family: courier new;"&gt;and() &lt;/span&gt;and &lt;span style="font-family: courier new;"&gt;or() &lt;/span&gt;functions (they are not provided by WinRunner) and I used them to make a bit collection of matches of a table row. With each table row check, the correct bit was set to 1 or 0 in case of a match or a non-match.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;But this rowcheck function was very slow. More then 3 minutes for a 25x25 table for example.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;First, I didn't bother about the bad performance, we did a lot within a check: Negative checks, regular expressions and other exotic stuff to support the testers. But the rowcheck function got used more and more and the long idle times became annoying.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;We created a lookup table for the powers of 2, optimized the loops and conditional statements, but it still underperformed.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Then, we measured the time for a "&lt;span style="font-family: courier new;"&gt;x = and(a, b);&lt;/span&gt;" call and it was 1 tenth of a second. This means more then one minute in case of 25x25 checks, and we not only used it onced, but three times in one iteration.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;I assumed that the &lt;span style="font-family: courier new;"&gt;and()&lt;/span&gt; function had to be fast, because it was fast in C, the language the external lib was written in.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;After changing the bit collection through &lt;span style="font-family: courier new;"&gt;and()&lt;/span&gt;s and &lt;span style="font-family: courier new;"&gt;or()&lt;/span&gt;s to an array and performing calculations on the array (the product as an &lt;span style="font-family: courier new;"&gt;and()&lt;/span&gt;, the sum for an &lt;span style="font-family: courier new;"&gt;or()&lt;/span&gt;) the performance was increased to 23 seconds for a 25x25 table check. Even with regular expression and negative testing in place.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; font-family: verdana;"&gt;5. Function calls can be slow&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Whenever a function is called, a function is created on the stack, initialized, executed and destroyed. Processors are fast nowadays, but it still takes some time.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;I used to use&lt;span style="font-family: courier new;"&gt; isEmpty({variable})&lt;/span&gt; and &lt;span style="font-family: courier new;"&gt;isNotEmpty({variable})&lt;/span&gt; for a check on empty or not. The only thing the function did was:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;public function isEmpty(inValue) {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return (inValue == "");&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;It seemed smart on that moment, because if we created other definitions for empty, we just have to enter it in the function to implement it everywhere in the system. Unfortunately, we never came up with other definitions. We noticed, the isEmpty(myVariable) function was seven times as slow then a normal &lt;span style="font-family: courier new;"&gt;myVariable == EMPTY&lt;/span&gt; statement (&lt;span style="font-family: courier new;"&gt;EMPTY&lt;/span&gt; equals &lt;span style="font-family: courier new;"&gt;""&lt;/span&gt; in our system).&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;With this knowledge we replaced all &lt;span style="font-family: courier new;"&gt;isEmpty()&lt;/span&gt; functions in time critical functionality, such as the table row search function mentioned above.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;A little side note:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;myVariable == EMPTY&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;or&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;myVariable == ""&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;does not make any difference in WinRunner. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana; font-weight: bold;"&gt;Last word&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;As mentioned before, this is how you optimize code on a very low level. As long as your design is not right, use senseless synchronization timers or bad synchronization mechanisms, the  performance of your test will not increase significantly. Optimization must be in balance on all levels of the test process; From scripting automated tests to requirements and risks.&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1708518509752812818-5728524553423632274?l=automated-chaos.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://automated-chaos.blogspot.com/feeds/5728524553423632274/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1708518509752812818&amp;postID=5728524553423632274' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/5728524553423632274'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/5728524553423632274'/><link rel='alternate' type='text/html' href='http://automated-chaos.blogspot.com/2008/06/lowlevel-code-optimization-in-winrunner.html' title='Lowlevel Code Optimization in WinRunner'/><author><name>Bas M. Dam</name><uri>http://www.blogger.com/profile/07594616635957734329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_k--5h5XK9eM/SEUuZr6EL_I/AAAAAAAAABE/31zvGzZ-jWw/s72-c/power.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1708518509752812818.post-8878941543859089612</id><published>2008-06-02T20:28:00.014+02:00</published><updated>2008-12-10T21:15:01.279+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tricks'/><category scheme='http://www.blogger.com/atom/ns#' term='QTP'/><category scheme='http://www.blogger.com/atom/ns#' term='data entry'/><category scheme='http://www.blogger.com/atom/ns#' term='classes'/><category scheme='http://www.blogger.com/atom/ns#' term='testability'/><category scheme='http://www.blogger.com/atom/ns#' term='mercury'/><title type='text'>QTP and Tricks with Classes</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_k--5h5XK9eM/SERXv76EL-I/AAAAAAAAAA8/A7T58s1Vtc0/s1600-h/oil_imperium.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_k--5h5XK9eM/SERXv76EL-I/AAAAAAAAAA8/A7T58s1Vtc0/s320/oil_imperium.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5207383550193840098" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: verdana;"&gt; As a hardcore WinRunner test automater, I still not like the "one line, one statement" approach of VBScript, but the one thing I like is working with classes. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: verdana;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: verdana;"&gt;I'm still playing around with it a little bit and I learn a bit each day. The thing I did today isn't new I think, but for me it was.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: verdana;"&gt;&lt;br /&gt;A little about my situation. We are (ab)using QTP as a dataentry tool. We can only use the frontend, because the backend is protected. (so long for third party software). There will be a backend interface soon, but soon in the ICT is still counted in multiple months and a quicker solution had to be found. Maybe that is why QTP is chosen. On the contrary, I think the program manager felt for the 'Q'. Right now, the data is coming from multiple sources and will be directed to the frontend with QTP.&lt;br /&gt;&lt;br /&gt;And this is where I discovered a neat application of classes for the use in dataentry. I created a class, let's say "customer" and I redirected the class into a function as a method of that class.&lt;br /&gt;Time for an example:&lt;br /&gt;&lt;br /&gt;First, my class 'customer':&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;class customer&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public name&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public address&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public phone&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;end class&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;and my function to enter the customer into the frontend:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;public function enterCustomer(byRef myCus)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;i&gt;' Use byRef for speed and to save memory&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;call navigateToCustomerCreate()&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;i&gt;'I like functions more then subs&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;with Browser(zzz).Page(yyy)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: courier new;"&gt;&lt;span style="font-size:85%;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.WebEdit("Name").Set myCus.name&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.WebEdit("Address").Set myCus.address&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: verdana;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: verdana;"&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.WebEdit("Phone").Set myCus.phone&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;end with&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;end function&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;   &lt;br /&gt;&lt;span style="font-family: verdana;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: verdana;"&gt;now, I added a function into the customer class to enter the customer:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;class customer&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public name&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public address&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public phone&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public function enterData()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;call enterCustomer(me)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;i&gt;'The 'me' is referring to it's own class object 'customer'&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;end function&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;end class&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This creates a method for my customer object to enter my data.&lt;br /&gt;&lt;br /&gt;Because a customer can have multiple accounts, I created a class account and that one is added as a dynamic array in the customer class. And for data integrity I created a validate method that checks if all mandatory fields are filled and if all data is in the correct formatting (hurray for regular expressions). &lt;br /&gt;But I can add as much functionality as I like in a ordered way, the only call I have to make to get it all working is using the enterData() method in my driver script for entering all my data into the frontend.&lt;br /&gt;&lt;br /&gt;The main reason why I use this method, is that I only have to write an import function for all three types of import (plain text, xml and through an ODBC connection) and redirect the data into the class. At the end I call myCustomer.enterData() and it is done.&lt;br /&gt;&lt;br /&gt;In the mean time, testing my functions is very easy, I just create an object of the correct class and test the function by calling enterCustomer(myCustomer). I don't have to bother validation rules because they are only executed when the enterData() method is called. And because the method validate() is a public method in the customer class, I do not have to enter the data when I want to test the validation of it.&lt;br /&gt;&lt;br /&gt;It seems a lot of work for only adding a customer but in the real situation, the datamodel contains a lot more objects with a lot more fields. This way, it keeps my code clean, structured and also important: testable.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1708518509752812818-8878941543859089612?l=automated-chaos.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://automated-chaos.blogspot.com/feeds/8878941543859089612/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1708518509752812818&amp;postID=8878941543859089612' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/8878941543859089612'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/8878941543859089612'/><link rel='alternate' type='text/html' href='http://automated-chaos.blogspot.com/2008/06/qtp-and-tricks-with-classes.html' title='QTP and Tricks with Classes'/><author><name>Bas M. Dam</name><uri>http://www.blogger.com/profile/07594616635957734329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_k--5h5XK9eM/SERXv76EL-I/AAAAAAAAAA8/A7T58s1Vtc0/s72-c/oil_imperium.jpg' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1708518509752812818.post-383286220061597644</id><published>2008-06-01T18:42:00.011+02:00</published><updated>2008-12-10T21:15:01.673+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dynamic class creation'/><category scheme='http://www.blogger.com/atom/ns#' term='QTP'/><category scheme='http://www.blogger.com/atom/ns#' term='classes'/><title type='text'>QTP and Four Ways of creating Classes</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_k--5h5XK9eM/SEL3h76EL7I/AAAAAAAAAAk/8Lp3AA_pnTo/s1600-h/skooldazesmall.gif"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_k--5h5XK9eM/SEL3h76EL7I/AAAAAAAAAAk/8Lp3AA_pnTo/s320/skooldazesmall.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5206996281582694322" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:verdana;"&gt;&lt;span style="font-family:verdana;"&gt;&lt;/span&gt;QTP isn't build for the use of classes. If it was, we had a separated file where we could store our classes, a viewer extension and a set of exotic functions with almost enough functionality to handle our custom classes.&lt;br /&gt;But we haven't have any of them, so we have to fiddle around with methods Mercury (I refuse to call them HP until their service is to the level we are used to experience) thought we are not capable of to use: &lt;span style="font-style: italic;"&gt;'Coz we're testers - not programmers.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;These are four methods to implement classes. I found the last three on the net, the source is just down each method.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;1. Just put them in your action script&lt;/span&gt;&lt;br /&gt;And enjoy the experience of non-reusable classes. Just the main benefit of a class: reusability is taken away from you, because with each new action script, you have to define your class again (if you want to use it of course). This will only suit you if you only have one action script.&lt;br /&gt;This is the case on my current project, because we don't use Quality Center and we use the action script more as the main driver then as what it is meant to be.&lt;br /&gt;I still rather don't want to use it in the way I just described, because with only ten classes in our data model it is still getting crowded in the action script.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;2. Put them in a function script&lt;/span&gt;&lt;br /&gt;You can put your class into a separate function script and just add it to your project. But QTP wouldn't be QTP if this worked on first glance. As long as you only put it in there as a class, it wouldn't work, because in some way the class is seen as a private on that function library. It will not be recognized in other parts of your script.&lt;br /&gt;&lt;br /&gt;The work around:&lt;br /&gt;First, make a class&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;class prototypeContact&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public name&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public address&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public phone&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;end class&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;and create a function (in the same library), setting an object as that class and returning that object:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;public function Contact()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;set Contact = new prototypeContact&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;end function&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Now you can use your class by calling the function with a newly created object:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;set myContact = Contact()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The function Contact() will assign a new object to myContact of the class prototypeContact.&lt;br /&gt;&lt;br /&gt;First found on &lt;a href="http://www.softwareinquisition.com/2006/09/classes-objects-and-quicktest-pro-9"&gt;The Software Inquisition&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;3. Put them in an external script&lt;/span&gt;&lt;br /&gt;Create your classes in a new script and save it as .vbs file. From your main script (or action script), do a call to this library with ExecuteFile().&lt;br /&gt;&lt;br /&gt;This works with one major drawback, you'll have a hard time debugging. As soon an error is raised, it will mention the line of your main script were ExecuteFile() was called and that's it.&lt;br /&gt;&lt;br /&gt;First found on a &lt;a href="http://www.softwareinquisition.com/2006/09/classes-objects-and-quicktest-pro-9#comment-3970"&gt;comment&lt;/a&gt; on an article of The Software Inguisition.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;4. Load them dynamically&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;This is the most complex way, but also the one with the most potential. I will not go into the deepest detail, you can read that in the &lt;a href="http://abouttesting.blogspot.com/2008/04/qtp-debug-class-for-dictionary.html"&gt;original article&lt;/a&gt;, but I will explain the principle:&lt;br /&gt;&lt;br /&gt;1. Dynamically create a text string that contains the class definition.&lt;br /&gt;2. Execute the text string with the command "Execute" (for the WinRunner and Javascript readers: It does the same as the eval() function).&lt;br /&gt;3. Now you can set an object as the just created class.&lt;br /&gt;&lt;br /&gt;Because you create the string dynamically, you can adapt the class on the fly. I wouldn't dare to talk about inheritance or polymorphism, but you can imagine the power of runtime named classes, variables, objects, functions and properties.&lt;br /&gt;&lt;br /&gt;There is still the drawback of item 3: It gives you a hard time debugging it when something went wrong. And that is a very big drawback if you think about bugs that can enter dynamic written code.&lt;br /&gt;&lt;br /&gt;First found in an article on the blog of &lt;a href="http://abouttesting.blogspot.com/2008/04/qtp-debug-class-for-dictionary.html"&gt;Stefan Thelenius&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Final Word&lt;/span&gt;&lt;br /&gt;Not all methods are working on each release of QTP. ExecuteFile() for example is available as of version 9.0. You'll have to find out what method suits you best.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1708518509752812818-383286220061597644?l=automated-chaos.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://automated-chaos.blogspot.com/feeds/383286220061597644/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1708518509752812818&amp;postID=383286220061597644' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/383286220061597644'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/383286220061597644'/><link rel='alternate' type='text/html' href='http://automated-chaos.blogspot.com/2008/06/qtp-and-four-ways-of-creating-classes.html' title='QTP and Four Ways of creating Classes'/><author><name>Bas M. Dam</name><uri>http://www.blogger.com/profile/07594616635957734329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_k--5h5XK9eM/SEL3h76EL7I/AAAAAAAAAAk/8Lp3AA_pnTo/s72-c/skooldazesmall.gif' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1708518509752812818.post-2619055209521588749</id><published>2008-06-01T14:00:00.010+02:00</published><updated>2008-12-10T21:15:02.066+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='transition'/><category scheme='http://www.blogger.com/atom/ns#' term='QTP'/><category scheme='http://www.blogger.com/atom/ns#' term='pitfalls'/><category scheme='http://www.blogger.com/atom/ns#' term='winrunner'/><title type='text'>WinRunner to QTP transition: Pitfalls to avoid (part I)</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_k--5h5XK9eM/SELy-b6EL4I/AAAAAAAAAAM/BmnrbleOoGA/s1600-h/pitfallsmall.gif"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_k--5h5XK9eM/SELy-b6EL4I/AAAAAAAAAAM/BmnrbleOoGA/s320/pitfallsmall.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5206991273650827138" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;&lt;span style="font-size:85%;"&gt;Just since a while I am making my test automation scripts in Quick Test Pro. After working and dreaming in WinRunners TSL for six years, this was quite a change. Things that were easy in WinRunner, became not that easy in QTP, but the use of classes and objects made things better.&lt;br /&gt;&lt;br /&gt;Down here some issues I had to cope with.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;No incrementation shortcut&lt;/span&gt;&lt;br /&gt;As obvious as hell, I cannot get used to the lack of ++, --,+=, -= and other short ways to increment, multiply etc. Nothing else to do then pointlessly call i = i + 1 on an (expensive) single line of code.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;No 'continue' in loops&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;Within WinRunner, I used 'continue' just as often as the 'break' command. There is no substitute in QTP for this command, so you have to think out your flow properly, because you can only exit a loop (by 'exit {looptype}') and not start from the beginning from anywhere within the loop.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;No fall-through in 'select case' flow&lt;br /&gt;&lt;/span&gt;This becomes more and more a "drawback" list of QTP, but the thing I miss is the fall through mechanism of switch/case or select/case. Of course it is called Visual &lt;span style="font-style: italic;"&gt;Basic&lt;/span&gt;, and starters will often forget a 'break;' statement at the end of a case, but the C like switch is very powerful at the moment you get used to it.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;One time function evaluation in QTP&lt;/span&gt;&lt;br /&gt;This one is less obvious, but important for WinRunner users. In WinRunner you could write code like this:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;while (obj_exists(myObj) != E_OK)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;web_refresh(myFrame);&lt;/span&gt;&lt;br /&gt;Each time the while loop is entered and looped, the obj_exists() function will be called and evaluated. Within QTP a function that is called as part of the initiation of the loop will only be evaluated once. In this case the loop will never be exited when the object is not available the first time the loop is entered.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;All functions in an if statement will be handled in QTP&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;/span&gt;In C like languages, if statements are lazy. An example:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;if (set_window(myWin, 1) == E_OK &amp;amp;&amp;amp; obj_exists(myObj, 10) == E_OK) { ...&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;WinRunner would evaluate the first function (the setting of the window) and  when  this results in an error, the other function in the if statement is skipped because of the AND: the if statement can never evaluate to TRUE anymore, so processing the other evaluation makes no sense.&lt;br /&gt;Visual Basic like languages like QTP don't bother this kind of logic. In such kind of construct, QTP will evaluate both functions, no matter the outcome.&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1708518509752812818-2619055209521588749?l=automated-chaos.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://automated-chaos.blogspot.com/feeds/2619055209521588749/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1708518509752812818&amp;postID=2619055209521588749' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/2619055209521588749'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/2619055209521588749'/><link rel='alternate' type='text/html' href='http://automated-chaos.blogspot.com/2008/06/winrunner-to-qtp-transition-pitfalls-to.html' title='WinRunner to QTP transition: Pitfalls to avoid (part I)'/><author><name>Bas M. Dam</name><uri>http://www.blogger.com/profile/07594616635957734329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_k--5h5XK9eM/SELy-b6EL4I/AAAAAAAAAAM/BmnrbleOoGA/s72-c/pitfallsmall.gif' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1708518509752812818.post-6187444141989982580</id><published>2008-06-01T11:32:00.007+02:00</published><updated>2008-12-10T21:15:02.316+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tricks'/><category scheme='http://www.blogger.com/atom/ns#' term='winrunner'/><category scheme='http://www.blogger.com/atom/ns#' term='mercury'/><category scheme='http://www.blogger.com/atom/ns#' term='coding'/><title type='text'>WinRunner and why I like TSL</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_k--5h5XK9eM/SEL7E76EL8I/AAAAAAAAAAs/_oRHe-4DdAE/s1600-h/c64Heart.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_k--5h5XK9eM/SEL7E76EL8I/AAAAAAAAAAs/_oRHe-4DdAE/s320/c64Heart.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5207000181412999106" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:verdana;"&gt;I like TSL. Not because of its lack of classes, structs, function pointers or other fancy eighties C stuff, but because you can write powerful code on a single line. I like it even more since I am now developing my test automation in QTP. Yeah, that's right, the tool that uses crippled Visual Basic Script.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;"&gt;One nice thing in WinRunner is that you can use assignments inside functions or validations like:&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;for(i = 0; (rc = obj_exists(thisButton = “{class: push_button, location:”i”}”)) == E_OK; ++i)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;button_press(thisButton);&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;pause(i-- “ button” (i != 1 ? “s were” : “ was”) “ pressed.”);&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;"&gt;The three line above contains interesting code, I'll walk through it.&lt;br /&gt;&lt;br /&gt;First, this contains an assignment in function:&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;obj_exists(thisButton = “{class: push_button, location:”i”}”);&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;"&gt;And second, an assignment on validation like:&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;(rc = obj_exists(&lt;span style="color: rgb(51, 51, 153);"&gt;myObj&lt;/span&gt;)) == E_OK&lt;br /&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:verdana;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-style: italic;font-family:verdana;font-size:85%;"  &gt;&lt;span style="font-family:courier new;"&gt;thisButton = “{class: push_button, location:”i”}” &lt;/span&gt;is replaced by &lt;span style="color: rgb(0, 0, 153);"&gt;myObj&lt;/span&gt; to make it more readable.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;"&gt;Notice the parenthesis around the assignment; Normally assignments have a lower precedence, that is why we need it.&lt;br /&gt;(Explanation:&lt;br /&gt;If you use code like this:&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;rc = obj_exists(myObj) == E_OK&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:verdana;"&gt;first &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;obj_exists(myObj)) == E_OK&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt; &lt;span style="font-family:verdana;"&gt;is evaluated to TRUE or FALSE. Since rc gets that value assigned, rc becomes FALSE in case of a none existence of the object and TRUE otherwise, making the statement as buggy as hell; FALSE and E_OK both have the same value: 0, causing rc getting a E_OK value in case of a not existing myObj.)&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;"&gt;The last line contains a short cut for an if else statement:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;(validation ? value if true : value if false)&lt;/span&gt;&lt;span style="font-family:verdana;"&gt;&lt;br /&gt;This is great when you want to write fast code in a (log)message. Otherwise the same line would take you at least four lines if you want to state it properly.&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;1.   &lt;span style="font-family:courier new;"&gt;if (i == 1)&lt;br /&gt;&lt;/span&gt;2.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;pause("1 button was pressed.”);&lt;br /&gt;3.   else&lt;br /&gt;4.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pause(i "buttons were pressed.");&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: verdana;"&gt;The code in the example above is nothing worth in the sense of readability, but more to show the power of writing C-like lines of code. I would challenge the same functionality in a Visual Basic script like language. I think it will be 5 times more lines of code and a lot of debugging, since it is easily forgotten that VB(S) functions in "for" statements are evaluated only once. More on this another time.&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1708518509752812818-6187444141989982580?l=automated-chaos.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://automated-chaos.blogspot.com/feeds/6187444141989982580/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1708518509752812818&amp;postID=6187444141989982580' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/6187444141989982580'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/6187444141989982580'/><link rel='alternate' type='text/html' href='http://automated-chaos.blogspot.com/2008/06/winrunner-and-why-i-like-tsl.html' title='WinRunner and why I like TSL'/><author><name>Bas M. Dam</name><uri>http://www.blogger.com/profile/07594616635957734329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_k--5h5XK9eM/SEL7E76EL8I/AAAAAAAAAAs/_oRHe-4DdAE/s72-c/c64Heart.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1708518509752812818.post-961809330576264897</id><published>2008-05-31T14:13:00.004+02:00</published><updated>2008-12-10T21:15:02.583+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='add watch'/><category scheme='http://www.blogger.com/atom/ns#' term='secrets'/><category scheme='http://www.blogger.com/atom/ns#' term='sprintf'/><category scheme='http://www.blogger.com/atom/ns#' term='call chain'/><category scheme='http://www.blogger.com/atom/ns#' term='print'/><category scheme='http://www.blogger.com/atom/ns#' term='winrunner'/><category scheme='http://www.blogger.com/atom/ns#' term='mercury'/><category scheme='http://www.blogger.com/atom/ns#' term='coding'/><title type='text'>WinRunner Hidden Coding Features</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_k--5h5XK9eM/SEMBSb6EL9I/AAAAAAAAAA0/gJT8rKVkqX8/s1600-h/print.png"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_k--5h5XK9eM/SEMBSb6EL9I/AAAAAAAAAA0/gJT8rKVkqX8/s320/print.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5207007010410999762" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;&lt;span style="font-size:85%;"&gt;WinRunner has certain features that are not commonly known. This is a list with the most powerfull ones:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;print {statement};&lt;/span&gt;&lt;br /&gt;In non-batch mode, this will print the outcome of a statement/variable or string to an output screen. Great for debugging and much faster (and less annoying) then the pause() function. This function is not documented in the help files, only as a registered word (a word you can not use as a name for a custom variable or function).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;sprintf(format, variable, ...);&lt;/span&gt;&lt;br /&gt;This function works like the (s)printf in C, but without an out variable. The return value is the formatted string.&lt;br /&gt;&lt;br /&gt;Example:&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(153, 0, 0);"&gt;percCompl = 78.22845;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(153, 0, 0);"&gt;A = sprintf(“Completed: %0.2f%%”, percCompl);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(153, 0, 0);"&gt;# A == “Completed: 78.23%”&lt;/span&gt;&lt;br /&gt;For a complete overview of format characters, search the internet on sprintf() or get a C/C++ guide.&lt;br /&gt;&lt;br /&gt;Although this function can be found in the WinRunner users guide, it is highly underestimated. It works great for getting "check" variables in the correct formatting without bothering string manipulation.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Use Add Watch as direct execution window&lt;/span&gt;&lt;br /&gt;Use the Add Watch to see variable values during runtime and/or after pausing a test.&lt;br /&gt;While pausing a test, you can enter direct functions into the add watch window and evaluate the return value. So you can check during runtime if objects are existing and if certain functions are working properly. The shortcut to Add Watch is CTRL+w.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Use the call chain in the Debug menu function to find out function callers and callies.&lt;/span&gt;&lt;br /&gt;Within the callchain, you can jump from and to functions that are on the call chain; the values of the variables are still in place and you can use add watch to evaluate them (see section above).&lt;br /&gt;&lt;br /&gt;You can also use the call_chain_get_depth() and call_chain_get_attribute() WinRunner functions to write extensive debugging information to a log file. When you are used to the try/catch mechanism, you will certainly appreciate these two functions.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1708518509752812818-961809330576264897?l=automated-chaos.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://automated-chaos.blogspot.com/feeds/961809330576264897/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1708518509752812818&amp;postID=961809330576264897' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/961809330576264897'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1708518509752812818/posts/default/961809330576264897'/><link rel='alternate' type='text/html' href='http://automated-chaos.blogspot.com/2008/05/winrunner-hidden-coding-features.html' title='WinRunner Hidden Coding Features'/><author><name>Bas M. Dam</name><uri>http://www.blogger.com/profile/07594616635957734329</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_k--5h5XK9eM/SEMBSb6EL9I/AAAAAAAAAA0/gJT8rKVkqX8/s72-c/print.png' height='72' width='72'/><thr:total>0</thr:total></entry></feed>
