UFT 12.0 unable to synchronize an object using .Exists property - testing

from last few days i am trying to synchronize two objects that are dependent on each other for their execution.
EX: Object B should execute only after the completion of object A.
Now, in my scenario, the Object A is taking some time to execute, for this I need to synchronize the two objects.
The Completion of object will result in an image which will tell the user that the process is completed successfully or failed.
Below is my code:
sLoop = True
Do while sLoop
If (Browser("ABC").Page("PQR").Frame("XYZ").Image("BatchSuccess").Exist) then
msgbox "in if"
sLoop = false
Else
msgbox "in else"
sLoop = true
End If
Loop
Other Activities...
My IF condition is getting executed before it gets satisfied.
there is an image of ongoing process which the UFT is considering as the successful...
Note: there is also an image while executing the object. (observation, UFT is not able to distinguish between these 2 images)

Try to use WaitProperty method. Exist will return true when it finds Your object in app.
For example
objectA.WaitProperty(optionFromObjectSpy,someSpecificContent)
optionFromObjectSpy - innerhtml etc.

Just by looking at your code and your question, one thing pops right into my head is that you can use wait time inside your exist statement.
Like :
If B().P().Image().Exist("10") Then *'you can change the 10 second to anything you want*
'Code here
End If
Or Alternatively you could create a function that will check if readystate of the browser (assuming its IE) is 4 or not.
do while ie.readystate <> 4
Wait(1)
Loop
Call the function before doing anything with the Image object. Should work.

Try something like -
While not Browser("ABC").Page("PQR").Frame("XYZ").Image("BatchSuccess").Exist
Wait 1
Browser("ABC").Sync
Wend
'your code here after object A is synchronized
Browser("ABC").Page("PQR").Frame("XYZ").Image("BatchSuccess").Click

Related

Changing a CheckBox's Font Attribute "Strikethrough" from a specific module does not work

Using VBA (Excel 365 (16.0.12527.20880), German) I'm trying to set the strikethrough property of a checkbox (Checkbox1) caption to False in accordance to the Office VBA reference this should work.
The following code is placed in a Module1 (simplified) and changes the strikethrough-value of UserForm1.Checkbox1 (UserForm1 and Checkbox1 is static, created via the VBA-Editor, not via code during runtime).
Sub ChangeCheckBox()
UserForm1.CheckBox1.Caption = "Test" 'this triggers the Init-Procedure, which only sets the Height and Width of the UserForm. This shouldn't effect the problem, but I'm mentioning it here so it's clear that the form has been initialized. But if I leave it out, it's the same problem.
'Pre-Test - works fine
'Check initial value
Debug.Print UserForm1.CheckBox1.Font.Strikethrough 'returns false (as it should)
'Write value and check it
UserForm1.CheckBox1.Font.Strikethrough = False
Debug.Print UserForm1.CheckBox1.Font.Strikethrough 'returns false (as it should)
'Write value and check it again
UserForm1.CheckBox1.Font.Strikethrough = False
Debug.Print UserForm1.CheckBox1.Font.Strikethrough 'returns false (as it should)
'This next line seeems to cause the post-test failure
tmpString = ThisWorkbook.Worksheets("Sheet1").Cells(tmpIndex, tmpColumn).Value
Debug.Print tmpString 'returns the correct value
'Post-Test - fails!!!
'Check initial value
Debug.Print UserForm1.CheckBox1.Font.Strikethrough 'returns false (as it should)
'Write value and check it
UserForm1.CheckBox1.Font.Strikethrough = False
Debug.Print UserForm1.CheckBox1.Font.Strikethrough 'returns true (should still be false)
'Write value and check it again
UserForm1.CheckBox1.Font.Strikethrough = False
Debug.Print UserForm1.CheckBox1.Font.Strikethrough 'returns true (definitely should return false now)
End Sub
In my case, for some reason, the command sets the box to True instead of False. So far I pinpointed the problem to a specific line of code. The "Pre-Test" succeeds, the "Post-Test" fails (everything else works fine). Note, I'm using debug mode via step by step, no other code is executed "in-between".
The problem persists if I create a different Form and try the same thing there. The original procedures are several hundred lines of code, but I created the Testprocedure above and the problem persists. I can also reproduce it by creating a new Excel file from scratch with just one Sheet, one Userform/Checkbox, and one Module containing the test procedure.
So, why the hell does tmpString = ThisWorkbook.Worksheets("Sheetname").Cells(tmpIndex, tmpColumn).Value cause the "Post-Test" to fail?
Note: This error can not be reproduced on all machines, I tried it on a different machine. There, I can not reproduce the error.
I cannot reproduce the issue and I've tried on 3 different machines.
However, I remember seeing a similar issue about 7 years ago and I managed to work around it by first checking if I need to change the value of the font property.
Try replacing all occurences of this:
UserForm1.CheckBox1.Font.Strikethrough = False
with this:
If UserForm1.CheckBox1.Font.Strikethrough Then UserForm1.CheckBox1.Font.Strikethrough = False
This basically sets the .Font.Strikethrough property to False only if it is already True because otherwise it is False (obviously) and if there is any bug in the setter of that property then this skips the bug.
Unrelated to your question but it's not a good idea to use the default instance of a Userform like you're doing here with Userform1.Checkbox.... I recommend you read this article written by #MathieuGuindon back in 2017.
Try using index for your worksheet instead of the name.
Its a funny thing to happen in a programming language.
tmpString = ThisWorkbook.Worksheets(1).Cells(tmpIndex, tmpColumn).Value
Debug.Print tmpString
It worked for me and I think because the polymorphic functions in VBA made without debugging! because nothing else could cause this kind of behavior!
I've managed to reproduce the issue the same way it occured to you.
The root cause here is that you are not explicitly UNLOADING the form after you close it, which means that all modifications that you made to it while open get retained in memory.
For example using your code, shows the checkbox with strikethrough even when running it 2nd time. Which means it's retained in memory.
So to fix this, simply add Unload UserForm1 in your procedure after running the code.
While this approach works in resetting the checkbox (which I assume is your ultimate goal here), it still returns true for those last 2 checks for some reason. To workaround that as well (though it could be unnecessary if you achieve your goal), then simply use #Cristian Buse's if/then solution.

Macro single step works when routine doesn't

I have been running this macro and it come up with an 424 Object Required Error but the macro works and I get the expected result when I run it with a single step button "F8".
Sub FileUpload()
Dim IEexp As InternetExplorer
Set IEexp = CreateObject("InternetExplorer.Application")
IEexp.Visible = False
IEexp.navigate "https://www.google.co.uk/?gws_rd=ssl#q=lenti+a+contatto+colorate"
Do While IEexp.ReadyState <> 4: DoEvents: Loop
Dim inputElement As HTMLDivElement
Set inputElement = IEexp.Document.getElementById("brs")
MsgBox inputElement.textContent
IEexp.Quit
Set IEexp = Nothing
End Sub
The error comes up on the Set inputElement = IEexp.Document.getElementById("brs") line.
You’re checking the ReadyState of the browser, but with some modern web pages the DOM isn’t actually updated with some objects until at least that point.
IE automation in VBA is quite primitive, and it sounds like in this scenario you’re trying to access a node in the DOM before it exists - despite your best efforts to wait until the browser is ready. In some cases this can literally be a matter of milliseconds out in timings.
Your quickest fix here is to simply add Application.Wait() in your loop to cause an actual time delay. A more elegant option might be to introduce a check in your loop and exit the loop when the desired DOM object actually exists. If you do this, there’s a danger of ending up in an infinite loop and so I would always recommend setting a maximum number of increments as a backup.

Keeping Application running

I am trying to keep an application open until a file appears. I am using a timer to check the FTP server every 60 seconds (file could take 13 to 15 minutes before it shows up).
The while loop works...but it takes up 50% of my CPU. Trying to figure out another way. I was looking into adding a Windows.Form and using the Application.Run(), but was wondering if the Application.Exit() would close my application.
Public Shared Function CheckStatus(ByVal TaskID As String) As Boolean
_TaskID = TaskID
'Start Timer to Check Query Status Every 10 Seconds
CheckStatusTimer.Interval = 10000
CheckStatusTimer.Enabled = True
CheckStatusTimer.Start()
'Wait for Check Query Status To Complete
While _Status = False
End While
CheckStatusTimer.Stop()
CheckStatusTimer.Enabled = False
Return _Status
End Function
Could placing the CheckStatusTimer.Stop() into completion logic section of my CheckStatusTimer_Tick() Subroutine. How can I prevent the calling function from returning until the timer is stopped?
Thanks
jlimited
The thing you are looking call is called Thread.Sleep():
While _Status = False
System.Threading.Thread.Sleep(500)
End While
This means the thread will check every 500 milliseconds (0.5s) if the Status is different.
This what you need to work with a task in background:
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker(v=vs.110).aspx?cs-save-lang=1&cs-lang=vb#code-snippet-2
Another thing, these lines are wrong:
CheckStatusTimer.Stop()
CheckStatusTimer.Enabled = False
You're repeating, start() method and enabled=true property perform the same thing, also stop() method and enabled=false
Here's a tutorial of how to download a file in background mode
http://msdn.microsoft.com/en-us/library/ms229675(v=vs.110).aspx

VBA: test for top of call stack

I would like to test if a procedure is called directly by the user (so it is on top of the call stack, see ctrl+L in debug mode) or called from another procedure.
Does someone know a way to do this without tracking the call stack in a parameter passed in each procedure?
I tried to do this using a public parameter topOfCallStackFound and then adding to each procedure some code like:
select case topOfCallStackFound
case false
currentProcedureIsTopOfCallStack = true
topOfCallStackFound = true
case true
currentProcedureIsTopOfCallStack = false
end select
But this doesn't work because VBA remembers the value of topOfCallStackFound after code execution is finished! The lifetime of topOfCallStackFound only ends when the workbook is closed, an end command is given or in a few other not useful circumstances. If it is possible to end the lifetime of topOfCallStackFound when code execution is finished and/or reinitializing topOfCallStackFound to false when the user starts new code execution, I would be done.
Thanks!
in VBA there is no normal way to see the callstack.
This is because the accessing this callstack via api is part of the low level compiler that is not part of the VBA.
You can view the callstack view the windows, as the VBE compiles the VBA and runs it and therefore has access to the VBA callstack but it does not expose it to the VBA.
You can however use try to use something like this:
http://www.everythingaccess.com/vbwatchdog.htm

Exiting from a VB.NET With block

In the following block of code, does VB.NET gracefully exit the With block if Var1 = 2?
With MyObject
.Property1 = "test"
If Var1 = 2 Then
Return True
End If
.Property2 = "Test2"
End With
Return False
I remember this being an issue in VB6 and causing headaches with unpredicable behaviour - is the same true of VB.NET?
According to MSDN, this still isn't possible:
If you need to exit before all the statements have been executed, put a label on the End With statement and use the GoTo Statement to branch to it. (...) You cannot transfer control either from outside a With block to inside it, or from inside it to the outside. You can call a procedure from inside the block, but control returns to the following statement.
Had to add another answer here, because I was mainly curious. Never used WITH much, and I can't recall ever exiting the block prematurely, but I just tested this under VB2010 and it appears to work just fine (ie as I would expect it to, in other words...
If Var1 =2, the function returns TRUE, and the value of MyObject.Property1 is "Test" but MyObject.Property2 has not be set.
It's possible that it worked this way in a test, but in a real app of significant size, with debugging turned off etc, etc, it could work differently, so, there's that to consider....