Virtual Objects

Segue’s 4Test programming language is an extremely versatile and powerful language, much like C or C++ in its syntax (turn of Visual 4Test and you’ll see just how much). However, unlike C++, 4Test is not a truly object oriented language. There are still some event-oriented carry-overs from the C world. As we know, window declarations are made up of three elements: the class of the object, the identifier for the object, and the tag of the object. The class of an object determines what methods will be available to that object. In the example shown at the right, there are a variety of classes. The DialogBox class has certain methods available to it, as do the StaticText, TextField, and PushButton object classes. For example, you can click on a PushButton and it does something. Clicking on a StaticText object won’t get you very far. You can change the text in a TextField object with the SetText method, but those methods aren’t available to StaticText or PushButton classes of objects. The tag of an object determines which object of that class will be acted on. In the example shown here, there are two TextField objects in the DialogBox. It certainly wouldn’t do much good if Silk were trying to act on the TextField named Password when the script really wanted the User ID entered into the UserID TextField object. Each object is unique in a number of different ways. In the example shown, the caption of the objects is used to determine the differences between them. The identifier of the object is merely a variable name. Just a way of referring to the object. In the example, “Login” refers to a DialogBox class of object that has a caption of “Login”. Likewise, the OK PushButton (Login.OK) is a variable that points to a PushButton object with a caption of OK that happens to be sitting upon a DialogBox with a caption of “Login”. All of these examples point to “real” objects. In saying this I mean that they are sitting there on-screen, can be acted upon, can be looked at and “touched” (with a mouse pointer, at least). There is a way, however, to use classes and methods and this object-oriented approach to deal with objects of a more nebulous nature. I think of this as dealing with virtual objects.

When working with objects, the only reason that Silk attempts to interact with an object or check for its existence before acting on it is because the object should have a physical presence on your desktop. Silk knows this because you have gone to the trouble of creating a window declaration for it with a class, an identifier, and tag. And when it comes right down to it, what you probably don’t realize is that the tag is the real kicker. If you were to create, say, a DialogBox object that has no tag, what do you think Silk would do when you tried to interact with it? Cause a compile error? A runtime error? Have you ever tried it? Take a look at the example shown here. The results may surprise you. Because the object being acted upon has no tag, Silk inherently understands that it doesn’t exist and doesn’t even try to act upon it. Just leaves it alone and goes on its merry way. However, the really interesting part is that the GetClass method returns that it’s a DialogBox. Because that’s what it is declared as. So…what’s the point? If you can create objects that Silk will not try to act upon, and they don’t really exist, can you write methods in them? Can you store data in them? Consider the example shown here. I’ve created two DialogBox objects which don’t exist. In each of them I’ve stored different data but with the same names. Changing just one variable, wData, I can change all of the associated data. Granted, this would be just like creating a record data type, but I can’t create methods in record data-types. If I change the value of wData to Data_2, the results of running the testcase will be very different. Another more real-world example of this is creating virtual objects like this for each user of a test frame. Each DialogBox object can hold information about that user such as a login name, a password, a security level, a certain directory that they need to use for their testcases, etc. And, programmatically by determining what user is logged into the system (GetUserNameA is a DLL call in 32-bit Windows advapi32.dll), switching which data set is used. Additionally, virtual objects can be used to group similar functions together. This will, for some -- particularly in large testing situations with a lot of functions -- make things a lot easier to find. Although some may think of this as a “merely organizational” tactic, it works very well. And on the occasions where holding down the control key and hitting the period key takes you to

the window declaration of an object, it will take you right to the function as defined. (If you didn’t already know that, Ctrl-. will take you to the window declaration of the object your cursor is on in some situations. It’s considered an “undocumented” feature by Segue since it’s untested and doesn’t always work. But it certainly does sometimes, particularly after a compile.)

If we can create “objects” that aren’t real, doesn’t it reason to believe that we can create entire classes of objects that we can then create instances of? Of course. One example that I’ve used a number of times while in the field when working in situations where I had to work with a lot of ASCII data files was creating a virtual TextFile class. In it I built methods for reading from and writing to ASCII files. Then I could create many instances of the TextFile class, defining as a data-member what file to access for each instance of the class, and all of the manipulation methods were built in to the object because they inherited the methods from the class. As you can see by the example shown here (incomplete, mind you), there are a number of methods built into this class for manipulating an ASCII file. Most of the methods are actually made up of other 4Test functions. For example, the Exists method merely calls SYS_FileExists, but it already knows the filename (the sFile data-member) to check for the existence of. Likewise, GetContents calls ListRead. By building all of the methods into the class, I can create many instances of the class and they will all have the same methods available to them. All I have to do is define, in the instance of the class, the sFile data-member so that the class methods know what file to work with. In the example shown here, there are instances for both the system’s autoexec .bat and config.sys files. The instances are called Autoexec and Config, respectively.