4/04/2006 03:20:00 PM|W|P|Will|W|P|I wrote this function this afternoon after being frustrated by the lack of decent checkpoints in QuickTest. I hope you find it insightful.
Public Function assertSucks ( sString, sEvent )
Dim sSuckMessage, bSuck, sNot
sNot = "not"
bSuck = False
If sString = "checkpoints" Then
bSuck = True
sNot = "indeed"
End If
sSuckMessage = "Expected Suckitude. " & sString & _
" does " & sNot & " suck."
assertSucks = reportStatus( bSuck, sEvent, sSuckMessage )
End Function
|W|P|114418257299935626|W|P|assertSucks|W|P|paperhat@gmail.com4/05/2006 06:34:00 AM|W|P| Theo|W|P|ROFL!!!! Some of my functions have more...colorful names as well. It's frustrating to have to replace native "functionality" with your own because the native "tools" do indeed suck....
Thank you for this...a great laugh to start my day. :-)
Theo4/03/2006 11:39:00 AM|W|P|Marcus|W|P|The changes to the management of the Object Repository are among the most significant in the new version, and though I haven't been through enough with the product to have a comprehensive opinion, I wanted to post my initial thoughts, and to invite comments from anyone whose experience is similar or different.
First off, let me say that on our team, where possible, we use programmatic descriptions. We minimize our interaction with the OR because we find that this is usually the first area that breaks when something changes in the interface. But we still do use the OR, and we rely on having an easy way to interact with it. I'm happy to report that they have made improvements in version 9, but there are still cases where they didn't go far enough.
The Set Up
In the description below, I opened a new test and associated my AUT's shared repository with the default action. My first inclination was to remove the association between the action's default Local Repository, but then I found that you can't remove the association. In an initial fit of consternation I talked it over with Will, and he was happy about the new behavior.
The Team-Oriented Object Repository
The local vs shared OR is their solution for how to make a team repository easier to manage: during test development, you have read-only access to the objects currently in the repository, but new objects are added to the local repository for that action. At some point later, one test developer goes back in and merges all the objects that should be shared, and either trims the rest from the local, or leaves them there if there's no chance of them being used outside that action.
I'm undecided about this method, but I understand why they've done it. One thing is for sure: this beats the heck out of trying to run the external merge tool every few days, not having any idea when new objects are being created, and all the other stuff we had to do in 8.2 to get it working.
The New Object Repository Interface
When you open the new Object Repository, the first thing you'll notice (besides the fact that it now takes about 5 seconds on my machine, as opposed to less than half a second for version 8.2), is the tree view on the left and the properties frame on the right. Further, the default size for the OR is more like what you'd expect: with the hierarchy collapsed to 3-deep, you can really see things well. The frame is big, and you probably don't have to scroll around much. When you click on an object, the properties frame on the right automatically refreshes to show the selected object's properties.
You'll further notice that the tree is mostly grayed out - that's the shared repository in read-only mode. Local objects are read-write, and any new objects you add go into that. The nice thing about this is how the trees merge seamlessly - if you're adding a new WebElement under a particular browser/page object, one that exists in the shared OR, its hierarchy is copied into the local rep so that it looks like your new WebElement is actually under the same parent as all the other WebElements on that page. This allows you to view the OR the way you always have, and since the files are separated, you won't be stepping on someone else's code, forcing a merge.
Here's the BIG problem with the interface: For the read-only objects (in the shared OR), you can't get extended attribute properties. You can't view them at all. The only properties you can see are the Description Properties, used to identify the object, the Ordinal Identifier, and whatever Additional Details you have turned on with Smart Identification for that object type. Now, I believe 8.2 worked in the same way if you were working with a read-only repository, but since that's the rule now and not the exception (on our team, anyway), it becomes tiresome to go through the steps necessary to view the additional details.
This probably wouldn't gall me so much if I didn't see all that space below the properties that are listed... space where they could have put reams and reams of information, separating TO Properties and Method calls, allowing you to view anything and everything at will. It's a missed opportunity to put all that good information right there on the page.
So what do you have to do to see the properties? Well, you have two options, one easy, one hard. The easy one is this: select the object whose properties you want to view, then click ObjectsCopy to Local from the menu bar (there's no hot key), then click the plus + sign in the Properties frame... this will allow you to CRUD all the TO properties. The side effect of this is that, if you end up making a change to the object, the change will only be made in your local repository, and will not be carried back to the shared OR.
The other option is to open up the Object Manager, a standalone app that allows you to merge ORs, edit properties, reparent, etc., independently from the main QTP interface. I'll be doing a separate write-up about the new OM, because though it's similar to the OR editor, it has its own set of features, annoyances, and tricky behaviors.
Locate in Repository - the Coolest New Feature
This is the coolest thing in the new OR - the ability to click on an object in the AUT, and have it highlighted in the OR. Was it just me, or did everyone else spend an awful lot of time searching for objects in the OR, navingating through trees and trees of crap, when the object on the page was just sitting there laughing at you? Now you click the "Locate in Repository" button, click on the object in the AUT, and it goes right there - if it can find it. It's a safe bet that if QTP can locate the object during a test run, it can locate it in an OR. It doesn't always work, but it's better than the nothing we had before.
Update from Application
Another cool feature: Select an object in the OR hierarchy, then click on its counterpart in the AUT, and its properties will be updated from the AUT. This is useful for when something is out of date, but I can see it being a pain if a whole page's worth of objects has changed and you have to update them all one-by-one. I don't know if there's an effecient way out of this yet, but it's possible that I've missed it. At any rate, I like the fact that it's there.
...and the Bad
They didn't put the "Locate in Application", "Copy to Local", "Highlight in Application", or any of the other object-specific functions in the right-click menu when these objects are highlighted... and it makes me want to scream. There are no appreciable hot keys, no ways to make management of these things more efficient, and you end up getting just about as frustrated as you did in version 8.2.
A really big problem, one that I'm afraid is going to cause many headaches for some really smart people, is that under the File Menu there's an option called "Export Local Objects". When my eye first hit that, I read it the same way I read "Copy to Local" from earlier, that it would perform some sort of merge with the shared OR. So, I could copy the objects to the local OR, edit them at will, then export them back out to the shared OR. No problem, right? Well, this options actually creates a new OR (the binary .tsr file format, not an XML file, by the way), containing the objects from the Local Repository. The intent is that you can create a standalone OR, and maybe use that as a shared OR for other actions. The actuality is that I once overwrote my humongous shared OR with objects from a local one, because like most normal people, I didn't read the warning message that said "this will replace the selected OR!!", clicked OK, and immediately heard groaning coming from a cube or two away. We're all version controlled here, so it was fine, but I'll bet dollars to donuts that someone less organized is going to lose a Lot Of Work as a result of this little detail.
Overall
In the end I haven't worked with the new OR enough to have a firm grasp of what's great and what's bad about it. These are my initial impressions, and I would invite anyone (even from Mercury, since we know you're reading ;) ) to help me to understand if I'm wrong on the new features. I've tried to stick mainly to the in situ OR dialog, because this is already long enough, so next time I'll cover the standalone Object Manager application.|W|P|114364272889907451|W|P|New Object Repository Interface in QuickTest Pro 9|W|P|mmerrell@gmail.com4/03/2006 03:33:00 PM|W|P| |W|P|Don't see any contact email so I'm putting this here - just wanted to thank you guys for these VERY informative articles. We are just getting started with QTP here and there is a lot of stuff here that is going to help us find the right answers when we weren't even sure what the questions were. Please continue, it is appreciated.4/03/2006 03:56:00 PM|W|P| Marcus|W|P|Thanks! Feel free to comment anytime you have questions or anything. We're making it our mission to be the best resource on QTP short of Mercury themselves.4/05/2006 02:37:00 PM|W|P| |W|P|Thanks for the qtp 9 info - I'm wary about upgrading and it's helpful to hear someone else's experience w/ it who uses it similarly.4/03/2006 09:17:00 AM|W|P|Will|W|P|When deciding whether a piece of code should go in a reusable action or a function, we usually favored functions in QTP 8.2. When Mercury introduced QuickTest 9, they made the argument for functions even more compelling with the Multi Document Interface. Now we can open as many function libraries as we want, but we are still limited to one test. So, if you want to edit a reusable action in another test, you have to close your current test, open the second test, make your changes, save and close the second test then reopen your original test.
In addition to that new argument for functions in QTP 9, the same old arguments from 8.2 still apply. I'll sum up a few of the key differences between reusable actions and functions here.
Passing Data
Actions - can only accept primative data types as parameters (strings, integers, etc)
Functions - can accept arrays, dictionary objects and test objects (i.e. Pages, Frames, WebRadioGroups, etc.)
Resource Usage
Actions - For each action, there’s a folder, three separate vbs files, a local Object Repository, a subfolder containing snapshots, an Excel spreadsheet, and a few seconds of load time.
Functions - There’s the code contained in the Function, and that’s all
API
Actions - You cannot insert calls to Existing Actions through the QTP API, you can only do it through the interface
Functions - You can attach Function Libraries to Test Scripts through the QTP API
Return Values
Actions - Return values are difficult to understand and read in the syntax
Functions - Return values work like they do in other languages (i.e. as lvalues)
UPDATE:
In comments, Jugular Bean points out a significant downside to functions that I neglected above. You cannot change the number of parameters that a function accepts without affecting all calls to that function. That is a problem that used to drive me crazy. It seems like every time I put a new function in a library, the next test I write needs that function with one extra option. Now that I use the getopts function to define the parameters in my functions, I can easily add new optional parameters without messing up other tests that already call the function.|W|P|114407493650475182|W|P|Actions vs Functions in QTP 9.0|W|P|paperhat@gmail.com4/03/2006 09:52:00 AM|W|P| |W|P|Hi, as a frequent reader I find your site very interesting, and helpful as a QTP user!!!
Few thing you forgot to mention in this post, when using functions you there isn't hierarchical arrangement of the test results.
And more important, what do you recommend to use actions or functions???4/03/2006 12:05:00 PM|W|P| Marcus|W|P|That's an interesting point about the hierarchical arrangement of test result, and it represents how a methodology for one team may not work with another.
Our test scripts are still divided into actions, and in these actions, our functions put Reporter.ReportEvent calls all over the test results. You can't see that we're in a function when you view the results, but the point is that the event is still there, still registered under the test action. It may not be as granular as you need, but it's worked well for us.
We use actions to organize our test scripts into test cases. We use functions for just about everything else. Before the MDI in QTP 9, we used External Actions all over the place, even for the smallest modular pieces of functionality. We've spent the last couple weeks converting the most critical code from actions to functions, improving the parameter interface, and reporting more events to the results.
So, the short answer is, I strongly recommend functions over actions for small bits of modular functionality. We use functions now about 90% of the time.4/03/2006 11:37:00 PM|W|P| Jugular Bean|W|P|For doing some logical task a function is useful. But for modularising the workflow of the app one is testing, I prefer Actions.
2 Useful features of actions when compared to functions
- Number of parameters can be increased at any time without affecting already existing action calls.
- Can return more than 1 output parameter
It's unfortunate that they have so many disadvantages, otherwise I'd use them over functions anyday.4/04/2006 04:16:00 AM|W|P| |W|P|One more issue that may be acute. while exploring this matter I found out that it is not possible to use "Step-into" in debugging mode when using library functions, into the library functions, which means the function code is like a black box while debugging. this can be one hack of a lack.4/04/2006 01:59:00 PM|W|P| Marcus|W|P|As of version 9, they've fixed the black-box problem wrt functions. You can now debug and step through and develop and open as many as you want. It's awesome, and probably the best feature of version 9. We'd never use them as much as we do if they hadn't fixed that part of it.
Besides the black-box problem, Jugular Bean's objections were the original reason we didn't use functions more. I hated the signature-change implications implicit in functions until Will developed the GetOpts method. Since then it hasn't troubled us. I hate that we've done so much work to avoid using their built-in mechanisms, but here we are.
As to the other point, about multiple output parameters, we tend to approach functions like you do in most other programming languages, where it's habitual to desire only one output parameter. If we need more than one, we use one of those cool hash-like structures like we use to pass arguments.
The fact that you can't insert actions into tests via the automation API was also one of the main reasons we switched. We're trying to produce code that generates QTP code, and without the ability to insert references to actions, the only thing you can do with them is to have them already inserted into a template test script, then do a save as, then overwrite the mts file, and execute. With function libraries, you just add the libraries, insert the code, and you're done. There is no test template, and you can be much more assured that it will work without broken links.
Dynamic QTP code generation is just about the best thing we've done with our approach, and one that I'll describe in-depth someday, when it's a little more baked.