In this article, we will see a few interesting ways to automate the Windows Calculator. To ensure the concepts in this article are not too overwhelming, I have divided it into 2 parts. The first one discusses a few basics and creates a routine that can be used to easily set values to, and retrieve from it. The concepts in this article should also serve as an excellent way of understanding the automation process with QTP, how functions can help increase code reuse, and why at times its extremely important to validate user-input.
[Off-topic] If you find this article helpful, and would like to see other types of applications automated as well, please post in the comments section and let me know what other applications would be excellent for conceptual purposes and I will try my best to include them in the future articles. [/Off-topic]
Let’s launch the calculator through code:
SystemUtil.Run "calc.exe"Now, we have the calculator object launched. Let’s see if we can create a few statements in QTP that act as users to perform some calculations. For this example, let’s calculate 10*20:
Window("nativeclass:=SciCalc", "index:=0").WinButton("text:=1").Click '1 -> 1 Window("nativeclass:=SciCalc", "index:=0").WinButton("text:=0").Click '0 -> 10 Window("nativeclass:=SciCalc", "index:=0").WinButton("text:=\*").Click '* -> 10* Window("nativeclass:=SciCalc", "index:=0").WinButton("text:=2").Click '2 -> 10*2 Window("nativeclass:=SciCalc", "index:=0").WinButton("text:=0").Click '0 -> 10*20 Window("nativeclass:=SciCalc", "index:=0").WinButton("text:==").Click '= -> 10*20= MsgBox Window("nativeclass:=SciCalc", "index:=0")_ .WinEdit("nativeclass:=Edit").GetROProperty("text")
Notice we have substitued a “\” before *. This is because * is a special Regex character and all special regex characters must have “\” before them to identify them correctly. You can also execute the same code without the “\” and test the result.
The above code can be simplified using a With..End With statement:
With Window("nativeclass:=SciCalc", "index:=0") .WinButton("text:=1").Click '1 -> 1 .WinButton("text:=0").Click '0 -> 10 .WinButton("text:=\*").Click '* -> 10* .WinButton("text:=2").Click '2 -> 10*2 .WinButton("text:=0").Click '0 -> 10*20 .WinButton("text:==").Click '= -> 10*20= MsgBox .WinEdit("nativeclass:=Edit").GetROProperty("text") End With
I covered the above With..End With block because at times when properties change, you only have to update the property of the Window object once, and not 8 times as you would in the previous code snippet.
We can still simplify this process further, by creating a function. With the help of the function, we can avoid writing long and the same lines of code each time we need to perform the same operation. This saves time, and when you need to make changes, it simplifies maintenance and increases code reuse. Let’s create two functions, then. One will type the key, and the other will retrieve the output from the calculator:
'vKey: Key you want to press Function TypeKey(vKey) '* is a special regex character 'We will put a "\" before it to let QTP know that we are using a literal, not a regex Select Case vKey Case "*" vKey = "\" & vKey End Select With Window("nativeclass:=SciCalc", "index:=0") .WinButton("text:=" & vKey).Click End With End Function
Function CalculatedValue CalculatedValue = Window("nativeclass:=SciCalc", "index:=0")_ .WinEdit("nativeclass:=Edit").GetROProperty("text") End Function
Create a function library and copy both functions in it. Then, go to “File” menu and click “Associate Library [LibraryName] with ‘Test’”. Right now, your library should look something like this:
Let’s now use the function that we have created above to perform the same calculation. In your test, you will have:
TypeKey "1" TypeKey "0" TypeKey "*" TypeKey "2" TypeKey "0" TypeKey "=" MsgBox CalculatedValue
Notice how we have compacted our code from the very first code snippet to the one above.
We have already talked about substituting a “\” before a special regex character. The calculator has 5 keys that include such characters. They are:
* + +/- . M+
We need to incorporate all special regex characters above in our Select-Case block. Thus, we’re now ready to manipulate the TypeKey function above, and create one that will input all sorts of keys from the users, make sure the special characters are followed by a “\” sign, and retrieve the output from the calculator.
Function TypeKey(vKey) 'Use a Select block for special regex characters Select Case vKey Case "*", "+", "+/-", "." vKey = "\" & vKey Case "M+" vKey = "M\+" End Select With Window("nativeclass:=SciCalc", "index:=0") .WinButton("text:=" & vKey).Click End With End Function
Our function is ready! It is now capable of taking any sort of input from the user and retrieve the output. Let’s put the above function in use:
TypeKey "1" TypeKey "*" TypeKey "2" TypeKey "+" TypeKey "3" TypeKey "=" MsgBox CalculatedValue
Now, we will begin with the tricky part. Well, not really. This is still the first topic, so we’ll keep it quite easy. We still haven’t created any sort of validation, yet. We are going to manipulate this code a few times and compact it further. We will do this to ensure that our script does not stop because of a user error. For example, if you type “10″ instead of “1″, then “0″, QTP will error out. That is because the calculator does not have any key greater than 9. In other words:
'This is Correct TypeKey "1" '1 exists in the calculator TypeKey "0" '0 exists in the calculator 'This is incorrect TypeKey "10" '10 does not exist in the Calculator
To avoid occurrence of such user errors, we can begin by creating an array of all keys available to the calculator:
Dim arrCalcKeys arrCalcKeys = Array("Backspace", "CE", "C", "MC", "MR", "MS", "M+", "sqt", "%", "1/x", "=", "/",_ "*", "-", "+", ".", "+/-", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0")
Now, we can run all our validations against this array. If a user enters any key that is outside this array, that means, there is an error which must be handled. This can help us create a function that will be used solely for purposes of validation. Let’s call it, IsKeyLoaded.
Function IsKeyLoaded(vKey) Dim arrCalcKeys, iCalcKey IsKeyLoaded = False 'Array with all Calculator Keys arrCalcKeys = Array("Backspace", "CE", "C", "MC", "MR", "MS", "M+", "sqt", _ "%", "1/x", "=", "/", "*", "-", "+", ".", "+/-", "1", "2", _ "3", "4", "5", "6", "7", "8", "9", "0") 'Loop through all Array items and attempt to find vKey For Each iCalcKey in arrCalcKeys 'If the Array Item matches with "vKey", Exit Loop. Return True. If CStr(iCalcKey) = CStr(vKey) Then IsKeyLoaded = True Exit For End If Next End Function
IsKeyLoaded contains the array we created above, and a For-Loop that will check the Input Key against the Keys in the Array. If the 2 keys match, we’re good. If the 2 keys don’t match, that means, the user entered an invalid value. But, we’re in the clear because we now have the error handling for that! This also means that because of an invalid input, our script won’t stop.
You won’t believe we have come this far, so quickly. Remember the “TypeKey” function we created earlier? We will incorporate “IsKeyLoaded” in “TypeKey” and create our validation component.
Function TypeKey(vKey) 'If Key is not found then, Exit Function If Not IsKeyLoaded(vKey) Then Exit Function End If 'Rest of the function remains the same: Select Case vKey Case "*", "+", "+/-", "." vKey = "\" & vKey Case "M+" vKey = "M\+" End Select With Window("nativeclass:=SciCalc", "index:=0") .WinButton("text:=" & vKey).Click End With End Function
Let’s put the code we have created now into practice. We will also use the “CalculatedValue” function we created earlier. For the sake of experiment, let’s provide our function with 2 invalid keys: A and B. Notice how these keys will not be entered to the Calculator, instead, the function will exit if it finds anything that is outside the scope of our array: arrCalcKeys.
TypeKey "A" 'Ignore TypeKey "1" 'Valid TypeKey "B" 'Ignore TypeKey "2" 'Valid TypeKey "3" 'Valid TypeKey "+" 'Valid TypeKey "1" 'Valid TypeKey "=" 'Valid MsgBox CalculatedValue '124
Our script didn’t stop regardless of the user error, and was able to retrieve the output nonetheless. However, there is a BIG short-coming in our code. If the user meant to type “0″ and they typed “A”, “B” or any other key, that means, even though our script didn’t stop, it calculated an incorrect value. A small error at times can go unnoticed, and it can become a cause of concern for the automation developer as well as the user. Thus, we must incorporate additional logic that will let us know if an invalid key was calculated; and the output should be discarded. We will see that, and much more in the coming article!
In this article we learned how we can begin from scratch and create a highly usable code block. In the next article, we will cover advanced techniques, and you will see how code can be compacted further, and how code reuse can be enhanced. Above all, we will learn why we must be sharp in reporting errors that a user might miss. Sometimes, our extra attention to detail can save an entire team a lot of time. Plus, your role automatically becomes more important to the success of the team.
If you have any questions, please ask them in the comments section. If your query is confidential, please use the Contact Form to send me an e-mail instead.
FaceBook
LinkedIn
Twitter
YouTube
{ 8 comments… read them below or add one }
Hey Anshoo,
the way u program and present logic is very good .
I m following and using urs tricks for last two years.
Expecting u help this community in future also (with out asking any consulting free)
Thank you for your kind words, Anil. I am deeply honored. :)
Hey Anshoo,
Very good one….
Your articles are helping me a lot in understanding and learning qtp….keep up the good work…hope to see many such good articles in future….
Radhika
Thank you!
Holidays are approaching now Radhika and my submissions are reducing exponentially :)
Hi Anshoo,
I am following your tips and tricks frm last 2 mnths.Its really working great for me..
Can we have some brief discussion on arrays ?
Some questions like:
How to use arrays for datatable to retrieve values?
How to use arrays for childobjects?
and some more….
regds,
Sachin
Sure, Sachin. That’s a great idea. I will try to write a post on this topic soon.
Hi Anshoo,
This way article is summed up quite nice, easy and simple. Great work !!!
When will add the next article (Automating Windows Calculator Part 2) in this series and update this article wih link to “Automating Windows Calculator Part 2″.
I am looking for some article where I can learn, how to design a KeyWord Dirven Testing Framework for QTP.
Please help. ASAP.
Akash Rastogi
9811170395
Hi Akash,
Thank you for your feedback!!
I am currently working on a few articles and have about 10 drafts which need to be published, including the part 2 of this article. It will be released soon :)
The following article shows the types of frameworks and gives some details as to what they do and how they are created: http://www.ibm.com/developerworks/rational/library/591.html
I hope this helps.