One of the nice things about SilkTest was the use of a dereference operator. I was disappointed to see that QTP didn’t have that. Yet I found you could start to mimic some of the functionality with the Eval function and the Execute statement.
In both cases you pass string arguments to these code constructs. In terms of why you would use one rather than the other, the main difference is that the Eval function will always return the result of the string evaluation. The Execute statement, on the other hand, will execute your passed-in string statement for execution but will not retrieve the result of that execution.
Here’s a common example that demonstrates this somewhat concisely:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
x = 100 y = 101 ' First Test setEqual = Eval("x = y") Execute "x = y" MsgBox "Equality: " & setEqual MsgBox "Value of x: " & x ' Second Test x = 100 setEqual = Execute("x = y") MsgBox "Equality: " & setEqual MsgBox "Value of x: " & x ' Third Test x = 100 Execute("setEqual = (x = y)") MsgBox "Equality: " & setEqual MsgBox "Value of x: " & x |
If you run that, you’ll see that in the first test the Eval function returns a Boolean value (False) whereas the Execute statement performed a variable assignment. In the second test, when I try to return the value from the call to the Execute statement, I actually got nothing back at all. The third test actually shows you how I can get the return value. In that case, however, you should notice that the call to the Execute statement did not actually change the value of x, whereas it did in the previous tests.
So now let’s move on to a quick example to check if an application window exists:
1 2 |
myApp = "SwfWindow(""name:=Home"")" Execute "MsgBox " & myApp & ".Exist(0)" |
Try that with your application both open and closed and you’ll see that you get a return value of True and False, respectively. I can actually do the same thing with the Eval function as well. This would basically just let retrieve the value directly which I could then store off:
1 2 |
myApp = "SwfWindow(""name:=Home"")" appExist = Eval(myApp & ".Exist(0)") |
Now I’m going to consider another example where I create an event on a SwfEdit object by creating an object hierarchy through strings. The trick is — and this is important — I’m doing this at run time.
1 2 3 4 5 |
myApp = "SwfWindow(""name:=Home"")" signOn = "SwfWindow(""name:=Home.SignOn"")" userCode = "SwfEdit(""name:=txtUserCode"")" setEvent = "Set ""JNYMAN""" Execute myApp & "." & signOn & "." & userCode & "." & setEvent |
At first glance you’re probably wondering why in the world you’d want to do that when you could just code the steps descriptively in your logic. That’s true. You could. If you knew the exact steps you wanted. But let’s say that the exact objects you are going to be using may have to differ based on other execution elements that you can’t code for ahead of time. In that case, you could build up the statement you want to execute at run-time as I did above.
Here’s another example that shows how QTP execution logic code can be executed via a succession of strings.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
myApp = "SwfWindow(""name:=Home"")" signOn = "SwfWindow(""name:=Home.SignOn"")" userCode = "SwfEdit(""name:=txtUserCode"")" password = "SwfEdit(""name:=txtPassword"")" login = "SwfButton(""name:=btnLogin"")" setUser = "Set ""JNYMAN""" setPass = "Set ""hypersurface""" doClick = "Click" doClose = "Close" Execute myApp & "." & signOn & "." & userCode & "." & setUser Execute myApp & "." & signOn & "." & password & "." & setPass Execute myApp & "." & signOn & "." & login & "." & doClick Execute myApp & "." & doClose |
Again, this may not seem like much: after all I’m just hard-coding the strings rather than typing out descriptive phrases. Again, that’s true: but consider that those strings would probably not be hard-coded in realistic examples. Instead, they are dynamic elements that would be populated based on changing execution parameters. And in those cases, Execute statements could be crafted that would respond to whatever those changing execution parameters are.
In fact, this kind of logic would be useful in framework logic. You could have data conditions that are retrieved from a data source. Those conditions are then parsed by logic in the framework into string statements. Once parsed, these string statements are then executed in the same manner as QTP code would be. You could also do this both for the objects themselves — building up hierarchies — and the events that need to be executed against those objects.
Where I’ve found this most useful is where you are building a QTP framework that has to execute tests in the context of in-depth scenarios or work flows, where changing conditions that come about as part of the test mean you are following an entirely different workflow and thus, potentially, an entirely different set of objects or a different set of interactions with the same objects. This is still an area I’m experimenting with but I’ve found it quite useful.