Can't determine if a certain UITestControl exists in my web app
Asked Answered
E

3

10

I'm currently trying to help automate some coded UI tests using C# for a web application. A frequent problem I'm encountering is that it can be extremely difficult to determine if a UITestControl object exists on the page or not. Unfortunately, Microsoft's documentation on their MSDN website for anything regarding coded UI tests is practically non-existant (see here their page for UITestControl).

Basically what I'm asking is:

  • What is the best way to determine if a UITestControl exists on the page or not?
  • How does the UITestControl.Exists property work?
  • What does the UITestControl.Find() method do?
  • How does the UITestControl.TryFind() method work?

How I've tried to handle it:

As I mentioned earlier, the documentation on all of these classes and methods is mostly blank. The most you can get to describe any of the methods and properties is a 1 line description in Intellisense, so I've been experimenting with the methods that are listed.

First I tried checking if the UITestControl.Exists property was true, but over time and consulting others' experience with it, it became apparent that it always returns true, even if the browser isn't open. Since the option that seemed most obvious wasn't working, I tried using the UITestControl.Find() method, but since it takes no arguments and returns nothing I couldn't figure out what it did. I tried using the UITestControl.TryFind() method, and occasionally it worked, but I found that it only seemed to return false when I wasn't on the correct page; it always returned true otherwise. Clearly I had no idea how it worked, and shouldn't use it as a test.

I figured if I couldn't get the provided methods to do their job, I'd have to try to make my own tools. I most recently tried using Mouse.Hover(UITestControl) in a try/catch block to determine if the control exists like so:

public bool DoesExist(UITestControl control){
   if(control == null)
      return false;

   try{ Mouse.Hover(control); }
   catch (UITestException)
   {
      return false;
   }

   return true;
}

It works sometimes, but in certain situations it seems to return false positives for reasons I don't understand. I'm still flying blind, and I'm nearly out of ideas.

I am using Visual Studio 2012, and Microsoft .NET Framework version 4.5.50709.

Einsteinium answered 13/11, 2013 at 18:52 Comment(0)
G
3

Partial answer about the Find() and TryFind() methods.

After setting the various search properties in the class instance for the control the Find() method does the actual searching for a control to match. The SearchProperties are used to try and find a control. If no controls are found then the search fails - forget exactly what happens then, possibly an exception is thrown but the documentation does not state that. If one control is found that the Find() completes. If two or more are found then the search continues by using FilterProperties to reduce the number of controls found to one.

The Coded UI recorder generates code of the style UIControl aControl = this.UIMap.uione.uitwo.uithree; which leads to the question of how does uione get a value referring to a control such that uitwo can be evauated? The only answer I have found is in the Description part of http://blogs.msdn.com/b/balagans/archive/2009/12/28/9941582.aspx which says "the search for the control starts ( explicit by Find() or implicit by any usage of the control in actions or property validations )".

So Find() performs the search for a control and it can be called explicitly or implicitly.

TryFind() is basically the same as Find() except that it returns a boolean indicating whether the control was found. Again, the documentation is poor but I believe that TryFind() returns true if exactly one control is found, false otherwise.

Another useful find method is FindMatchingControls which returns a (possibly empty) collection of all controls that match the search criteria.

As per yonitdm's answer, using the BoundingRectangle can help when there are multiple items that match but most are not on display. The values of Top and Left can also be used. Doing a FindMatchingControls and screening the results to ignore anything with negative Top or Left may work.

When developing tests the DrawHighlight method is useful, it draws a rectangle around a control. The same sort of rectangle that is drawn when recording assertions with the cross-hairs tool.

The Coded UI content index has lots of good information. The link to "How does UI Test Framework find (search) for a control" may be particularly helpful for you.

Grosgrain answered 13/11, 2013 at 22:42 Comment(1)
Thank you very much, any answers to any of those 4 questions is appreciated, even partial answers. One of the problems with TryFind() and Find() is that it's hard to discern how it interacts with procedurally-generated elements, from my limited understanding it seems to often fail to find elements that exist, and successfully find elements that have stopped existing or never existed to begin with.Einsteinium
P
1

Instead of using obj.Exists() we have coded our own exists method that uses a combination approach of EnsureClickable() and BoundingRectangle.Width>0 to make sure that the control has a screen point.

ETA- oops, sorry left off an important part. Updated to add .Width to make sure it's greater than 0, you may need to use length if you width is somehow not working.

Phytology answered 14/11, 2013 at 22:17 Comment(5)
Haha, I also am attempting to write my own. Will play around with these.Einsteinium
Bad news, EnsureClickable() passes without a hitch, and BoundingRectangle thinks that the button is in a spot near the upper-left corner of the page, halfway superimposed on the app logo.Einsteinium
The playback seems to believe that the non-existent button has a width, and that width has a value that button never gets.Einsteinium
So when you highlight the control from the UIMap and it's "not there" some area in the corner is highlighted? ugh, We had that. Output the length. Take a look at the control definition to see if it has anything useful, occasionally I've seen values with html and javascript that don't show up in the control properties but allow us to identify the object. Otherwise, sikuli? ducksPhytology
Still not sure what you mean by the length.Einsteinium
M
1

I am using tryfind() .. it is working fine.

if (obj_webor.GenLink.TryFind())
{
    logdata.WriteLine(obj_webor.GenInnerText + " Exist !");
}
else
{
    logdata.WriteLine(obj_webor.GenInnerText + " Does Not Exist");
}

Earlier i was using obj_webor.GenLink.exist().. but is was giving error if it was control not existing and exception occurs. tryfind is ok

Menderes answered 11/8, 2015 at 10:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.