For instance, when I click Button A, Button B is created, but until created, Button B doesn't exist. How would I check to see if Button B exists without failing if it does not?
I have tried Verify Exists & Verify ExistsNot, but both fail with an "Unable to locate element" and fail the entire test.
Please help.
16 Answers, 1 is accepted
instead of using Verify, use Wait (also found in Quick Tasks).
For instance: if a Button takes 10 seconds to appear "Wait - element exists" will wait until the element appears before the test moves on to the next step. Verify on the other hand would fail immediately because the element doesn't exist at the time of the verification.
Something else you can do is set your Verify step to "Continue on Failure" from the Steps View (see the attached screenshot). This will continue executing the rest of the test even if your Verify step fails.
I hope I've managed to answer your question!
The button isn't taking 10 seconds to appear. If it isn't there when the page has finished loading it WON'T be. Trying to do both "Wait.ForExists" and "Wait.ForExistsNot" both result in a failure being thrown when the control isn't there as shown below.
Failure Information:
~~~~~~~~~~~~~~~
Exception thrown executing coded step: '[oldLogin_IfSelect_DoThis] : If PossibleSelectControl exists, select index 0 to cause it to be replaced by a text control'.
InnerException:
System.TimeoutException: Wait for condition has timed out
at ArtOfTest.Common.WaitSync.CheckResult(WaitSync wait, String extraExceptionInfo)
at ArtOfTest.Common.WaitSync.For[T,V](Func`3 func, T target, V custom, Boolean invertCondition, Int32 timeout)
at ArtOfTest.WebAii.Synchronization.Wait.ForCondition(Func`3 condition, Boolean invertCondition, Object custom, Int32 timeout)
at ArtOfTest.WebAii.Synchronization.Wait.ForExists(Int32 timeout, Boolean refreshElement)
at ArtOfTest.WebAii.TestTemplates.HtmlElementContainer.Get(HtmlFindExpression expr, Boolean waitOnElement, Int32 timeout)
at ArtOfTest.WebAii.TestTemplates.HtmlElementContainer.Get(HtmlFindExpression expr)
at ArtOfTest.WebAii.TestTemplates.HtmlElementContainer.Get[TControl](HtmlFindExpression expr)
at ArtOfTest.WebAii.TestTemplates.HtmlElementContainer.Get[TControl](String[] clauses)
at CalendarTry1.Pages.WorkspaceLoginPage.get_LoginlistSelect() in c:\Documents and Settings\username\My Documents\WebUI Test Studio Projects\CalendarTry1\Pages.g.cs:line 73
at CalendarTry1.oldLogin.oldLogin_IfSelect_DoThis() in c:\Documents and Settings\username\My Documents\WebUI Test Studio Projects\CalendarTry1\oldLogin.aii.cs:line 137
------------------------------------------------------------
'11/16/2010 9:39:58 AM' - Detected a failure. Step is marked 'ContinueOnFailure=True' continuing test execution.
But the biggest reason that this fails to work is that when a single step fails, the entire test fails. The "Continue On Failure" doesn't change the fact that the test itself reports a failure as shown below.
'11/16/2010 9:39:58 AM' - Detected a failure. Step is marked 'ContinueOnFailure=True' continuing test execution.
'11/16/2010 9:39:59 AM' - 'Pass' : 3. [oldLogin_SetCredentials] : Set credentials for login.
'11/16/2010 9:40:04 AM' - 'Pass' : 4. Click 'LoginSubmit'
'11/16/2010 9:40:04 AM' - 'Pass' : 5. Verify 'TextContent' 'Contains' 'Logged in as: myName' on 'LoggedInAsSpan'
------------------------------------------------------------
'11/16/2010 9:40:04 AM' - Overall Result: Fail
'11/16/2010 9:40:04 AM' - Duration: [0 min: 10 sec: 484 msec]
------------------------------------------------------------
'11/16/2010 9:40:05 AM' - Test completed!
Is there any way around these hurdles?
I'm sorry this solution didn't work for you - I misunderstood what you were trying to do.
That being said, it seems what you need is Conditional Logical Statements.
Basically, you can do this:
If (element X exists) { do something }
And then you can add this at any point in the test where you think the element x is likely to appear. And it won't fail if the element isn't there, it will just keep going.
Another similar solution:
while (element X does not exist) { keep doing something or just waiting }
This will keep doing something or waiting until the element appears and will not time out or fail (though you probably will want it to time out at some point).
The best part is that you don't need to write any code to implement this stuff. I don't know whether you are aware but we've just released our Q3 release of WebUI Test Studio. One of the new features is adding Logical Statements from the UI without writting any code.
Ok, so first you need to get the Q3 release of WebUI Test Studio:
QA --> http://www.telerik.com/account/your-products/trial-product-versions/trial-single-download.aspx?pmvid=2313&pid=741
Dev--> http://www.telerik.com/account/your-products/trial-product-versions/trial-single-download.aspx?pmvid=0&pid=740
Install it right over your current version - it should be fine.
Once you have it check out the blog post on the new Conditional Logical Statements feature:
http://blogs.telerik.com/testing/posts/10-11-08/q3_2010_-_creating_if_else_statements_with_webui_test_studio.aspx
Don't miss the video tutorial: http://tv.telerik.com/watch/automated-testing-tools/conditional-logic-ifelse-statement-webui-test-studio --> I'm confident this will give you a very good idea how to use the feature in your own test: in the video they use the IF statement to check whether a text box contains "1" but it works exactly the same way with "Verify" and you can remove your Else statement if you don't need to do anything if the Element hasn't appeared.
Of course you can also implement this in WebUI Test Studio Dev Edition by adding Coded Steps and writting the logic yourself but it won't be any quicker or easier.
Please let me know whether this solution works for you!
Thank you for your assistance thus far, and let me explain the issue more clearly. You stated in your reply:
Basically, you can do this:
If (element X exists) { do something }
And then you can add this at any point in the test where you think
the element x is likely to appear. And it won't fail if the element
isn't there, it will just keep going.
Just to be perfectly clear, I have attempted the following different ways of "if (element x exists)" and they all throw failures when the control cannot be found:
Verify.Exists
Verify.ExistsNot
Wait.Exists
Wait.ExistsNot
If there is another way of doing the "if (element x exists)" please do let me know.
Let me interject and see if I understand exactly what you're trying to accomplish. Is the following correct?
- You want to verify whether or not an element exists
- If the element does exist do nothing
- If the element does not exist, log it and do nothing
- The test is marked Passed whether or not the element exists
If the test is marked Passed but the verification actually failed within the test, it's too easy overlook that little detail. We prefer to see "Test Failed" if any verification failed for any reason whatsoever.
To accomplish your combination can be done bug requires a coded step. Let's assume I have a Verify Element Exists test step as shown in the attached screen shot. Convert that step to code and then wrap it in a try-catch block like this:
try
{
// Wait for Exists 'DeveloperLink'
Pages.TelerikBing.DeveloperLink.Wait.ForExists(10000);
Log.WriteLine(
"PASS: The element was found"
);
}
catch
(TimeoutException)
{
Log.WriteLine(
"FAIL: The element was not found"
);
}
This this sample you will get a log entry in the tests log, but the test will always be marked Pass no matter what the result of the element verification actually is. Regards,
Cody
Now we've come full circle back onto the original function I was trying to do, to verify existence of a control without throwing an error (it's even the title of the original post). The reason that I did not want to throw an error was because the existence of the control is used to determine which of two logic paths the test should take, and here is why.
In Application X, there is a Log In screen. A user coming to the page for the first time is greeting with text inputs for both the user name and password fields. If the user has visited the log in page before and logged in successfully, they are greeted by a select control in place of the user name text control already filled with the name used the last time they logged in, and filled with any other names they've successfully logged in with.
I was attempting to use your product to devise a test that would interface with either the text control or the select control, depending on which control was present; and since your product can run tests through IE, Firefox & Chrome on windows each browser would be set up with a different initial state.
So, armed with the knowledge that I've gained through the several answers here, I need to answer the original question. I now know that I can use a try {} catch (error) {} to suppress the error message. Understanding the scenario that I have described above, would that mean that I would need to couch any logic that required the testing of whether a control doesn't exist in such a try...catch block? And this would also mean that I would be unable to use the "Logical" functionality as both IF...ELSE and WHILE...LOOP don't accept coded steps as their logic "switch"?
Thank you for your continued assistance.
I apologize it has taken so many rounds to get you a straight answer to your automation problem. Thank you for taking the extra time to explain in detail what you are trying to accomplish. See if I better understand it now. You want to:
- Navigate to your web page
- Perform some steps (such as login)
- If an element exists on the page, do block A, else do block B
- Do some more steps after the If Else block
Do I have the sequence correct now?
One technical problem we do have with the product is that trying to use a Verify Element Exists (or Not Exists) in an If Else block currently does not work as desired. It will abort the test if the element does not exist. This was a deliberate design decision by the development team. It was their goal to make text compares work with the If Else, but cause the test to abort of the element you wanted to test the text of didn't exist. The side effect of this is you can't use an Verify Exists in the If Else block. I believe this is the problem you are actually running in to.
Is there some other element that will always exist in both cases in which you can compare the value of? Or perhaps the property of some element that will always exist? This does work now with the If Else block.
The alternatives I can think of are:
- Don't use the If Else block. Have two separate tests, one for each case.
- Implement the If Else and the steps inside of them 100% within a single coded step.
We'll be happy to assist with either approach. Let us know and we'll help you as/when needed.
In addition I am going to bring this matter up with our CTO and explain how a critical test case such as yours is seriously broken with their current implementation. Hopefully we'll come up with a better solution in a near future release. I will update you with the outcome of that discussion.
Thank you for your patience as we work to improve our product and make it the best web application testing tool available on the market.
Cody
Folks,
I have just spent a couple of hours trying to do something that i consider the ABC of QA Automation and, i think, is along the same line of Philip's issue.
I have a Log In script - the epitome of simplicity.
My web app always have some control that is visible on the top span of the page (say, Logout link)
I want to do something VERY simple, namely, place the body of the script in an IF...ELSE construct.
IF <TheLogout Control Does Not Exist> THEN
navigate to the homepage
login
verify homepage is displayed
ELSE
In my experience of the past couple of hours (this is without writing code)
1. If i use Verify ExistNot - test fails on some exception (see indented text);
Overall Result: Fail
------------------------------------------------------------
'12/16/2010 6:09:18 PM' - Starting execution....
------------------------------------------------------------
'12/16/2010 6:09:27 PM' - 'Fail' : 1. IF (Verify element 'Home Link' 'is not' visible.) THEN
'12/16/2010 6:09:27 PM' - Unable to determine logical branch to go into. Unable to execute verification.
------------------------------------------------------------
Failure Information:
~~~~~~~~~~~~~~~
Unable to locate element. Details: Attempting to find [Html] element using
Find logic
(Html): [tagname 'Exact' a] AND [TextContent 'Exact' Home]
Unable to locate element. Search failed!
------------------------------------------------------------
'12/16/2010 6:09:27 PM' - Detected a failure. Step is marked 'ContinueOnFailure=True' continuing test execution.
------------------------------------------------------------
'12/16/2010 6:09:27 PM' - Overall Result: Fail
'12/16/2010 6:09:27 PM' - Duration: [0 min: 6 sec: 427 msec]
------------------------------------------------------------
'12/16/2010 6:09:28 PM' - Test completed!
2. If i use Wait ExistNot - the condition fails and the login body is always executed.
In most other QA Automation tools this is very easy to do.
I think it is a MUST FIX
We agree 100%. In fact if you upgrade to our SP1 release, 2010.3.1213 you should find this now works as expected.
All the best,Cody
Hi Mario,
Are you trying to adjust a test to use an if..else condition? Or you have troubles with a verification for an element which doesn't always exist on the page?
I will appreciate if you elaborate on your specific scenario and what are the troubles you experience. That way I will be able to assist you further.
Also, I noticed you are a customer of Test Studio, so you can also submit a private support ticket to continue the conversation if this will be more convenient for you.
Thank you for your understanding in advance! I am looking forward to hearing back from you.
Regards,
Elena
Hi
After I read all that I'm still having problems achieving 1 simple thing:
After I perform an action (let's say a button click) I would like to ensure that a TextBlock doesn't exist on Silverlight page. Before the click the TextBlock never existed on the page and after the click I would like to wait exactly 0.5s to ensure it still doesn't exist.
I thought I should use MyTextBlock.Wait.ForExistsNot(500) however it doesn't seem to work if the TextBlock never existed (exception thrown).
The trick with try/catch would work for me except the fact that I cannot precisely control the wait time.
Any solutions?
Not being an expert and having struggled with the same issue (except, i avoid coding like a plague), here's my understanding and how i resolve it (credits to Cody).
You begin by creating the situation where the control / widget DOES exist and create a "Wait Exists" on it.
(my understanding is that) this is when Telerik places the control in the repository so it can later be referenced.
In my humble opinion - this should do it.
If this still does not work then you may have repository issues similar to those created in mine - due to ignorance.
Bey
Sadly, your fix is moot in my case. I cannot "create the situation where the control DOES exist" with regards to the test.
I understand this to be "works as designed" with regards to the developers at Telerik. If you go up a few posts you'll see Cody from The Telerik Team's response as they, if I'm paraphrasing it correctly, chose abort when making a comparison in an IF .. ELSE block as a design decision. Until this stance changes, the problem will continue to require a convoluted workaround. Unfortunately, if memory serves (my trial has expired and I've been unable to extend it; another issue but not relevant to the current topic) that portion is also moot because even if you do use the convoluted coded step to allow you to step into the section of the test you want to, the failure is still a failure (even though it's captured within the step and dealt with) and causes the entire test to report a failure anyway.
So, for the original question of "How do I verify (non)existence of a control without throwing an error?" the simple answer is "You can't."
~ Philip
P.S. I do appreciate the suggestion, though.
I did not get too far with this argument.
@Filip Czaja
Thank you for alerting us of this problem. It is indeed a bug that MyTextBlock.Wait.ForExistsNot(500) will always throw an exception. I have fuiled bug 105454 to track this problem.
The good news is that a non-coded Wait For Exists Not step does work as expected. Also you can use a like of code like this to do the same thing:
Assert.IsNull(ActiveBrowser.Find.ByExpression(
new
HtmlFindExpression(
"src=http://col.stb.s-msn.com/i/B7/EB75D45B8948F72EE451223E95A96.gif"
,
"tagname=img"
)));
@Philip Antokal
We have fixed our Wait/Verify For Exists/ Exists Not descriptor so that it now works as expected in an IF ELSE block. You just need the latest version to obtain this behavior.
We have taken the deliberate approach that any other type of verification (e.g. textblock has certain text string) will abort the test unconditionally if the element that we're looking for to test the property of cannot be found.
For your specific case, if you cannot ever create a condition that the element does exist, how can we know what element to look for (i.e. what's the find expression going to be for it) so we can really check that it is not present at all? Maybe I'm missing something, but I can't see how can we verify an element is not there if we don't know precisely what to look for in the first place.
Cody
similarly i am also facing the same problem i.e .. how can we log multiple Error message in one function. that means Please find the sample code which i need to execute all steps in each function.
Code:
public void Function1()
{
string a = "Test";
string b = "Test1";
if(String.Equals(a,b))
{
Log.Writline("Both the strings are same");
}
else
{
Log.Writline(Logtype.Error, "Both the strings are not same");
}
Function2();
}
public void Function2()
{
Log.writeline("Test is in progress");
Log.writeline(Logtype.Error,"Test is in middle");
Log.writeline("Test is in Over");
}
In the above example i have to execute all lines of code depends on the if condition. please let me know how i can execute complete Function1 and Function2
Thanks
satyanarayana
As you may already know, passing LogType.Error to Log.WriteLine generates a LogErrorException. This causes the step to fail immediately without proceeding to subsequent lines of code.
One way to address this is to wrap the Log.WriteLine call in a try...catch block. For example:
Log.WriteLine("Test is in progress");
try
{
Log.WriteLine(LogType.Error, "Test is in the middle");
}
catch(ArtOfTest.WebAii.Exceptions.LogErrorException){}
Log.WriteLine("Test is in Over");
This pattern logs all three errors. Please let us know if we can help you further.
Byron
the Telerik team
Test Studio Trainings