Posts Tagged ‘QTP 9’

Test Design Studio

Wednesday, September 5th, 2007

I have spent most of the last few weeks working on QTP libraries, but very little of that time was spent wrestling with Mercury’s beast of an IDE. Aside from actually running my tests, I use QuickTest for very little these days. Instead, I am using a new editor called Test Design Studio. Everybody who uses QuickTest Pro’s expert view should try Test Design Studio. Once you do, you won’t go back to QTP.

Before we get too far into this, you need to know that Test Design Studio (TDS) isn’t a complete QTP replacement. TDS replaces QuickTest’s editor and library management, but it doesn’t actually run the tests. You use TDS to write tests and QTP to run them.

I could go on for pages about TDS’s features, but I won’t. You can see all of that at Patterson-consulting.net. Instead I will give you my first-ever top 10 list.

Top Ten Test Design Studio features that QTP is missing

10. Edit two tests at once – QTP is already on version 9.2 and they still haven’t figured out that users programmers might want to copy text from one test to another.

9. Excellent technical support – This isn’t technically a product feature, but it makes a big difference in using the product. I have submitted my share of help requests and bugs to Mercury, and I don’t think I have ever had an issue resolved within a day…rarely within a week. Patterson Consulting is another story. They will bend over backward to help you. Send an email to support or post in their help forum, and you have a good chance of getting a resolution within the hour. I haven’t called their support number, but I think I’m safe in assuming that if I do I won’t have to navigate through multiple levels of tech support before getting a resolution. The same can’t be said for Mercury.

8. Documentation Wizard – Automatically generate a help file from your code comments. If you maintain a large library, you know what a pain the documentation can be. TDS’s Documentation Wizard takes 90% of the work out of it.

7. IntelliSense for every class and function in your library – Don’t confuse this with QTP’s IntelliSense. TDS goes far beyond what QTP offers. With QTP, if you type Browser(oDescription), you will get IntelliSense for the various methods registered to the Browser type, but what if you have a function that returns a Browser object? You are out of luck with QTP, but TDS is able to tell that the function will return a browser. For instance, I often call the function BrowserDefault, which returns my default browser. With TDS, as soon as I type the period after the function name, I see all of Browser’s registered methods.
TDS Intellisense
I can’t do justice to TDS’s IntelliSense here. You’ll have to see it for yourself.

6. Customizable menus – You can put almost anything you can think of on any toolbar or menu. I recently worked on customizing the xslt file that defines the layout of TDS’s Object Browser. Instead of restarting TDS to try out changes, I added the “Reload ObjectBrowser.xslt” command to my tools menu. For most applications, that would be an internal-only call, but it looks like Patterson Consulting has made a point to make everything possible available to their users.

5. Hooks for external tools – There are still a few things that Test Design Studio doesn’t do. For that, there are external tools. For instance, I have an external tool set up that grabs all the vbs files in my project and adds them as resources on the active test. Another external tool is a vbs script that will open and run the current test in QTP.

4. Customizable Hot Keys – One of the few things I don’t care for in TDS are the default hot-keys assignments, but thanks to the customizable hot keys, I don’t have to remember that Ctrl+E,C is the command to comment out a block of text. It took about five minutes to make TDS match the Eclipse hot keys that I am used to.
Also, by combining this with the external tools mentioned above, I just have to press F5 to run the current test in QTP.

3. Code snippets – If you use Visual Studio, you already know what these are. I had not used code snippets before TDS, but I have come to find them very useful. I’m not sure that I can adequately explain code snippets in this post, so I’ll let Patterson explain it.

2. Macros – If you like to do the same thing over and over and over and over, this isn’t for you.

1. Search and replace throughout the project – Search and replace throughout the project is huge. Shortly after I started evaluating TDS, I changed the signature on a function. It literally took less than a minute to find and update hundreds of calls to that function spread over dozens of files.

There you have my first-ever top ten list. I hope you enjoyed it. I probably shouldn’t have numbered them because I just wrote them in the order that I thought of them. I also ran out of numbers before I ran out of features. If the list were a bit longer I would have included Object Browser, collapsible code outlining and xml-comments.

Mercury gives us SAFFRON

Friday, October 27th, 2006

Last week, Mercury posted a file for download called "QTP Expert Series - Issue 1". I saw it today and it interested me enough to download it. I'm certainly glad I did, because inside I found a spicy* little example framework called SAFFRON (Simple Automation Framework For Remarkably Obvious Notes).

SAFFRON is far from being a ready-to-use framework, but it does provide some good example code for creating an easy to read and write meta language that doesn't use an Object Repository. It is similar in concept to what the Inquisitors have been working on ... except a lot more light weight.

Here is an example from the SAFFRON FAQ:

QuickTest Script:

Visual Basic:
  1. Browser("Google").Navigate "http://google.com/"
  2. Browser("Google").Page("Google").WebEdit("q").Set "Hello World!"
  3. Browser("Google").Page("Google").WebButton("Google Search").Click
  4. Browser("Google").Page("Hello World! - Google").Link("Hello, World Page").Click

SAFFRON Script:

Visual Basic:
  1. BrowseTo "http://google.com/"
  2. EnterTextIn "q", "Hello World!"
  3. Activate "WebButton", "Google Search"
  4. Activate "Link", "Hello, World Page"

SAFFRON is extremely limited, but it is a step in the right direction. And it is good to know there is at least one person at Mercury who is doing some innovative thinking on test frameworks instead of focusing on how to apply the latest buzzword to the same old record and playback tests.

You can download SAFFRON on Mercury's support site or through this direct link.

* spicy...saffron...get it?

Classes, Objects, and QuickTest Pro 9

Wednesday, September 20th, 2006

VBScript is considered to be "object-based", meaning you can use classes, and those classes can have methods and members, but you can't get nearly the kind of re-use and extensibility you could out of a real OOP language. You don't get inheritance, you don't get polymorphism. In short, you get encapsulation, and that's about it. To me that's pretty important, the abilty to wrap up a bunch of common functions and attributes into a single entity called "an object" and throw it around kinda like you would in Java or Ruby. It allows me to create (instantiate) an object in line 10, then count on it being persisted three levels deep and 200 lines later, and never need to look inside the box to find out how it works.

I'll give some code first.

I'm using VBScript classes right now to model our AUT and make the code prettier. For example, if I want to create a user, it looks like this:

Visual Basic:
  1. LoginProfile "ADMIN"
  2. Set user = NewUser()
  3. user.create(“marcus”, “password”)
  4. user.addRole(“Administrator”)

This snippet opens a browser, logs in as an administrator, creates a new User object (basically a variable that holds attributes about a user), then uses that data (if I had supplied any) to actually create user from within the GUI. After the user is created and declared "valid", I call the "addRole()" method off of the same user. The User object knows how to fill out all the form fields. It knows how to add a role through the security interface. How? That's the beauty: I don't have to know. Someone else can develop the library of objects and maintain it, and all I have to know how to do is invoke it.

I know, I know, it's the same with functions. Yes, it is. But here they're all wrapped up together. Consider this:

Visual Basic:
  1. Set userGuest = NewUser()
  2. userGuest.create(“guest”, “password”)
  3. userGuest.addRole("Guest")

Later, if I want to know the name of that user, I can just ask the object:

Visual Basic:
  1. sName = userGuest.FirstName

Rather than have to code up a function to go and look it up somewhere. It's the persistance of data between states that I'm most interested in. The lack of inheritance and polymorphism is bad, but the most important problems are solved.

Here's the problem: in QTP, you don't just have the limitations of VBScript, you also have some severe limitations built in to (or rather "excluded from") QTP.

The class declaration (in a file called User.vbs) looks like this:

Visual Basic:
  1. Class User
  2.     Private sUserID
  3.     Public Function Init ( aOptions )
  4.         'do some proprietary stuff
  5.     End Function
  6.     Public Function create ( sUserName, sPassword )
  7.         'do some proprietary stuff
  8.     End Function
  9. End Class
  10.  
  11. Public Function NewTigerUser ( aOptions )
  12.     Set NewTigerUser = new User
  13.     NewTigerUser.Init ( aOptions )
  14. End Function

The first limitation:
That last function is there because QTP doesn't have the ability to use classes from external vbs files within the function libraries. You must give the test script access to the above function, which has access to the class, in order for your test script to be able to "see" the class.

The second limitation:
There's a bug in QTP where you can't, no matter what you do, use the debugger to step through class functions. That was almost a showstopper for me when doing this, before I learned just how few of me teammates use the debugger. When I found out I was the only one I decided that for the greater good, OO was a good direction to go in, if for no other reason than to make the code seem more familiar to us non-VBScript types.

So, in short, it's possible for us to get what we need to when we confront OO concepts, but we're severely limited by VBScript as well as Mercury. I'll submit defects on both of these issues, but I'm not sure whether I'd be optimistic about my chances. We seem to be the only ones trying to do this. Let me know if you know different!

New Object Repository Interface in QuickTest Pro 9

Monday, April 3rd, 2006

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.

Actions vs Functions in QTP 9.0

Monday, April 3rd, 2006

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.

New Interface Features, Quirks, and What-have-yous in QuickTest 9.0 - Part I

Monday, March 27th, 2006

This is just sort of a shotgun list of features and my opinion on them. It will also appear as a wish-list of sorts, as there are some opportunities they've missed in developing the QTP 9 interface. Keep in mind that I'm a big admirer of Spolsky, so what may sound like extreme nitpicking is to me a case of programmer-user disconnect. We who use this product are in the business of criticizing GUIs - we do it for a living... we should hold Mercury to the same standards to which we hold our own programmers.

  • Insert breakpoints by clicking in the gutter - great idea, but now it's very difficult to select a single line of code. In the past, if you clicked in the gutter, it would highlight the line of code you had selected. Now, if you want to select a single line, you have to put your cursor all the way to the left of the editor, but to the right of the gutter, then drag slightly down. Drag too much and you get two lines. Click in the wrong place and you either insert a breakpoint or you miss the first character in the line. I would have preferred this to be a checkbox option in the Editor Options menu.
  • New menu bar options - Now, instead of Test and Step in the menu bar, you have Automation and Resources. I don't know about you, but I got used to typing Alt+T, N for "Run Test" and ALT+S, A for "Action Properties". Now, it's ALT+A, N for "Run Test" (which is okay, because I just changed my habit to hit F5), but to go to "Action Properties", you have to hit ALT+E, I, P. No kidding. Action Properties are now in the Edit menu, under Action, then Action Properties. They've inserted a click in here, and it's a painful one because Action is almost all the way down the menu. That's another reason to go to functions instead of actions for most everything.

The Automation item is analagous to the Test item in 8.2, and they've made one huge change that I consider unnecessary and bothersome. They've moved Test Settings under the File menu. That's probably a more logical place, but here's the problem: in the past, when you couldn't remember where to go to change the Row Iterations, or what URL to use to open the browser, or Function Library references, chances were that if you chose Record and Run Settings and didn't find it, you could be assured that you could just choose "the other one in that menu" and it would be there. Now there are not one, not two, but three different places you have to go, none of them close together, in order to set up Test Run Settings. FileSettings, ToolsOptions, AutomationRecord and Run Settings - each of these menu chunks has the word "Run" in it, and who besides me can't remember which one has what?

One of my fondest hopes for QTP 9 was the ability to map many more functions to hotkeys. Alas, I'll have to wait a little longer. With the new clicks further obfuscating their most basic functionality, I'm find a lot of the seconds I'm saving on an improved feature taken away by another. I want to be able to go to Action Properties with a simple hotkey, but I can't map my own. This makes me sad.

I also can't change the annoying behavior that causes ALT+Backspace to erase an entire line of code instead of just the previous word. I don't know what interface precedent told them that was a good idea, but I'd advise them either to follow the Visual Studio interface (let's face it, the V in VBScript stands for Visual, which means Microsoft), or to give me mappings for every blessed function they provide. It's driving me nuts!

Ok, so I've covered the new menu bar and various niggling annoyances. Next I'll talk a little about the new window pane behavior, including the new right-click menu options and toolbars.

New Feature in QuickTest Pro 9: Multiple Document Interface

Monday, March 27th, 2006

This is first in a series of analyses of the new features of QTP 9. Over the next few days we'll be posting more in varying levels of deatil, and within a week or two we hope to have just about all of them covered. We'll try to address where they went right, but we're not going to leave out where they could have gone farther. Please add comments where you agree/disagree with out conclusions. We want to be an accurate source of information, so if we're wrong, TELL US!

In my opinion, the Multiple Document Interface is the best feature of version 9. It is going to alter how we address the question of External Actions vs Functions.

With the new interface you can have one test script open, and then any number of Function Libraries. Under the FileOpen and FileNew menu items, there's now a separate entry for Function Libraries, and the libraries do appear in the Recent File list. The function libraries then appear as tabs across the top. From these tabs, you can right-click and it will bring up a small menu with "Save" and "Close" for options. There's also a "Save All" button in the toolbar. All in all, it's nice.

But more importantly than any of these small victories, there are the larger implications of the feature: you can now view, develop, execute, and debug your functions.

In the past, I've written the function inside my test script, made sure it worked properly, then put it in the VBS file. Then, if I find a bug in my function, I've had to copy it back into my test script, then repeat the whole thing ad nauseum. It's even one of the things Mercury advises in their training materials.

Allowing me to write and debug the code in situ means I don't need to be afraid to write new functions, or groan when I find a bug. In fact, if I get to a breakpoint where I'm calling an external function, it will open the library and allow me to step into the code without the extra step of opening it myself.

With this feature, we plan to shift the way we develop our framework: since we have full freedom to develop code in small chunks, we don't always want to spend the necessary overhead to create External Actions. We'll only create actions in certain situations. I'll discuss this topic in detail under a different heading. For now, I just wanted to post a description of this nice new feature, and compliment Mercury on implementing it very effectively.

Next, I'll cover in detail the little interface changes they've made. Some good, some not so good.

Comparison of QuickTest Pro 9.0 vs QTP 8.2

Monday, March 27th, 2006

How do you measure the overall quality of a product? One way is to take the spec, take the final product, and compare the two feature by feature. Well, QTP 9 went GA today, and we've pored over it so thoroughly you'd think we've had it for months. First I'll present the summary, then over the next few days we will dissect the minutae of what they did, how well they did it, and whether or not it's going to make your lives easier. Here's a bullet-by-bullet summary of how well they did against their own press release:

  • Open and edit multiple Object Repositories - yes, the fact is that you can do this, but it's not always easy, and there were a lot of missed opportunities to go from good to great
  • Multiple Object Repositories per test asset - I hate the term test asset. I think in this case they mean Action, because as far as I can tell, there is no other "thing" you can associate an OR with, and in version 9 you can associate multiple ORs with any given action. There are problems with this, but I'll get to those later
  • Easy (Object Repository) conversion to/from XML - Yep, for what it's worth, the conversion is easy. It is very very very slow, and the schema is complicated, but both of those are pretty understandable.
  • Easily copy/move objects between Object Repositories - Yes, you can even drag/drop objects from one repository to another, but maybe more importantly, you can reparent an object... this is super-duper cool, because you can now take all the objects under "Frame_4" and "Frame_37" and consolidate them under "Frame". There are some HUGE problems with this feature that will probably be made easier in future releases, but it's still possible and nice when you just have to do one or two objects
  • Manage functions and keywords centrally - I don't know what this means, outside from the ability to view/edit functions from within the main IDE. If that's the case, they're kinda cheating in making this a separate bullet point from the "Step Into..." point below. If that's not the case, I have no idea what this means and shall declare it an example of "silly marketingspeak"
  • New user interface - sure, OK. It's not like the difference between vi and Visual Studio .NET, and they haven't provided an Eclipse plugin yet (note to self: write Eclipse plugin for QTP), but I guess they've made some changes
  • Missing resources panel - This is très cool, but not nearly as cool as the way they make it sound
  • Comment and uncomment multiple lines in Expert View - One of those little nice things they've done to provide features we're used to in every other programmer IDE on the market
  • Indent and un-indent multiple lines in Expert View - ibid
  • Pass parameters between Actions - I have no idea what this means, since you could do this before. Maybe they didn't broadcast that you could do it before. Whatever
  • Multiple Document Interface for function libraries - I guess this means you can open more than one function lib at a time. That's yet another restatement of the "Manage Centrally" nonsense from the earlier bullet. But I'm guessing they list it three separate times because it's simply the single best feature of version 9. It's changed the way we compose our tests, which is funny, because it essentially means that we use Mercury's scaffolding a lot less because they've made it easier for us to write our own
  • Step Into Function Definition Code While Debugging the Test - Yes, THIS RULES!
  • Enhanced IntelliSense Support - the main thing I notice here is that your user-defined RegisterUserFunc methods now appear in the code. Maybe that was there before, but I don't know. I could never make it work

Test Level and Checkpoints in QuickTest Pro (9 and earlier)

Friday, March 24th, 2006

We don't use Checkpoints at all in QTP. They're just not flexible to the degree that we need them to be.

Whenever you call a checkpoint, there's a lot of stuff going on, very little of which you have control over. You can put in some things that make it more flexible, like regular expressions and comparisons to other output values, but in the end you have this big black box of stuff that you can't really get at. Plus, in the end, you have a Reporter.ReportEvent that goes to the test results as a Pass or Fail, and you have no way to alter the strings.

The problem with that is, as I've said in previous posts, I want different tests to behave differently in different circumstances, but I don't want to rewrite any of the code. When I'm not running deep or strict tests, I want the test results to be sparse, just letting me know when the broad strokes of the tests have been completed. The Test Results Viewer that comes with QTP is difficult enough to use (e.g. it doesn't remember filter settings, etc.), so when I filter the test results based on pass/fail, I want to zero in quickly on the tests that were important to me when I ran the tests. Sometimes we use test actions as a means to an end, not an end in themselves, and in those cases I don't want to see every detail.

I have a lot of other problems with the checkpoints as they are, but some of my problems may be a lack of education. My team abandoned checkpoints too early to really explore the ins and outs and what-have-yous (mainly because of the reporting problem), so I'd like to hear from anyone who is still using them and gets what they need out of them. I'll state some of the problems below. I'm not 100% sure that I'm right on these, so pretend that with all of them I've added "This is the experience I've had, and I've seen no evidence to contradict it. If you have some knowledge to impart, by all means let me know."

Some of these problems are:

  • The Standard Checkpoints seem to be very, very slow. It's nice that you can look into specific object properties and all that, but the fact that it slows down the script is a real pain when you have a lot of them in there at once
  • For Table Checkpoints, you can't be at all flexible in column or row checking. Our application allows the user to change the order of columns, etc., which means we need to
  • For Text checkpoints, you must specify the nebulous "text before" and "text after", when, in my AUT at least, those things are seldom reliable or consistent
  • Worse yet, when it comes to localization, they'll be in a different language. You could specify values from a data table, etc., but sometimes I would rather be able to say "the text to the right of the object with XYZ properties", or "the text that is in this frame, and I don't care about the words, only that the font color is red and the CSS class reference is std_WarnText"

Like I said, there may be other ways to do this, but I haven't found them. When I have coded around things to shoehorn my checkpoints into working, I've often later found them to be very fragile. I had an occurrence recently of a long, drawn-out test script, that probably contained over a thousand lines of code. The one line of code that broke consistently and with no good error message was the one leftover checkpoint from my earlier days. I finally removed it and replaced it with our new, preferred method.

What is that new, preferred method? I'll talk about that soon. To give you a hint, think about JUnit.

In the meantime I want to talk a little more about Test Level, and the different levels we've defined. There are 6 levels, and we're retaining the option to have more. Each level gives an indication of how strictly it behaves, and how its behavior is recorded into the test results.

  • Test Level 0: Loosest testing possible. Try at all costs to be smart about selecting options, and just get through the code by any means necessary. Also, don't log anything that's not an error (and that's a QTP Run error, not a "test failed" error)
  • Test Level 1: Be as loose as level 0, but report all non-errors as "micDone" entries in the results. This way, we've at least kept track of all the things we've done, but when you filter by Warnings and Errors, you'll only get the stuff that was considered Very Important by the test developer
  • Test Level 2: Be as loose as level 0, but report all "smart" behaviors as warnings. When something doesn't exist in a WebList and you have to guess at it by clicking the first non-empty string, report that fact as a "micWarning". If the specified value was in the list, report it as a "micDone"
  • Test Level 3: Again, be as loose as level 0, but report all "smart" behaviors as "micFail", and all correctly specified values as "micPass"
  • Test Level 4: This time, don't be at all smart about how values are selected. If the developer specified something to be a certain way, report the problem as "micFail", then exit the test iteration (like QuickTest would by default, except that the intent is to give very detailed error information about what we were looking for and what appeared instead)
  • Test Level 5: Same as Level 4, but exit all test iterations immediately

The nice thing is that you can ratchet up or down the Test Level as the test goes on. You can test shallow in order to achieve some sort of setup, like object or scenario creation, then knock it up a level or two when you start the really important part of the test.

Our company has tasked us with asking a bit more out of our automated tests than is normally recommended. We understand that you're not usually successful when you try to do outrageously large regression tests, or to simulate manual scripts. But they want something in between "normal" automation and 100% regression coverage, and techniques like this allow us to move much closer to that goal than ever before.

The ability to take the same scripts that perform the low-level field validation, then employ them as "just a step along the way", has been paramount. It takes a while to develop the initial tests, but the development gets faster and faster as we build our library. Then, with very little effort, we can build a smart suite that can be reused against new builds, against customer-deployed sites, and against new versions of the product.

And we don't use Mercury's checkpoints anywhere.

Next, I'll post an example of another Smart method, the one we use for WebLists. It employs heavy use of Test Level to determine its behavior and logging.

Strictness in QuickTest (9.0 and before), Part II

Thursday, March 23rd, 2006

In our QTP framework, "strictness" has two dimensions: Test Level and Test Weight. Test Level refers to how loose the test is allowed to be when, say, selecting specific values from a WebList or WebRadioGroup. Test Weight refers to how important a given test is, and whether or not it will be run in the current cycle.

When we run tests, we run them at a default Test Level of 0, which is to say, "when you encounter a WebList or other input type, if the value I have specified does not exist, or only exists partially, just select a valid response and move on."

The Test Weight is 200 (out of a possible 1000). The lower the Test Weight, the more important the test. When you run a 200-weight suite, you are essentially running a smoke test, where you want to run the least number of tests to validate that the system is up and running. This is what we run every time Cruise Control deploys a new site. A suite level of 800 or 1000 tells it to run every stinkin' test we've written, and it takes much longer. That's what we run at 2 am when nobody is here.

Let's say I'm writing a QTP test where I create 15 new user accounts (each with different access features), log in as each, then perform existence checks on objects (buttons, checkboxes, etc) that should be enabled/disabled according to the access features. Given the number of different roles, features, and grants in our system, there can be over 800 permutations. Further, since we have between 4 and 8 hosted customer sites, this number mushrooms. As we host more customers, we want to scale our tests to be able to handle any number of customers, and we don't want to have to change to code to do so.

Even further, we want to design the code so that we can re-use all these actions (User creation, logging in, access checking, etc.) in other scripts where we don't want to run any checks beyond the most basic "did it work?" functionality.

Test Weight and Test Level are Environment variables, set in XML files, and altered at run-time to fit our needs (via an external utility). Each action has its own internal Test Weight, which is compared at run-time to Environment variable. If this internal Test Weight is greater than the weight of the suite being run, the action will short circuit and return to immediately without reporting anything or executing. If the internal Test Weight is less than or equal to the Environment variable, the test will execute.

Test Level is a lot more low-level. It is checked on a function-by-function basis, and the function in question always executes. The difference is, the Test Level will tell the function how to execute, then how to report its progress. An example would be (as above) a WebList, where you specify that "abc" be selected. If Test Level is 0 and "abc" doesn't exist in the list, it will take the first non-empty string in the list and just select it without looking deeper into the matter. The idea is that if I'm testing a site in a different language, or a customer-deployed site that contains completely different information, the test will still work just fine.

Having these two dimensions on our tests ensures that we can run exactly the same scripts on multiple databases with varying degrees of thoroughness as the situation dictates.

Next, I'll delve a little deeper into the different Test Levels we use, then I'll post the code for this WebList.SmartSelect method, and how it implements the concept.