Finding xpath dynamically or on the fly ...

Ask general questions here.
AppTester
Posts: 20
Joined: Thu Sep 29, 2011 12:11 am

Finding xpath dynamically or on the fly ...

Post by AppTester » Mon May 28, 2012 6:38 pm

Say I have 2 instances of Excel open. Here are the xpaths. Note the difference in @instance=

Code: Select all

/form[@processname='EXCEL' and @class='XLMAIN' and @instance='0']/element[@class='EXCEL2' and @instance='0']/container/element/element/container/button[@accessiblename='Maximize']
/form[@processname='EXCEL' and @class='XLMAIN' and @instance='1']/element[@class='EXCEL2' and @instance='0']/container/element/element/container/button[@accessiblename='Maximize']
Is there a way to dynamically determine the path of the UI control from either one of these workbooks? So if the paths change, or I'm not sure which instance to get during programming, is there a way to get the path on the fly, as the test case is executing?

For example if I hard code instance 0, the test case will crash if I try to click the button in instance 1.

I'm thinking, is there any code such as Ranorex.Button = GetPath("excel").ToString()
or
Ranorex.Button = "/form[@processname='EXCEL' and @class='XLMAIN' and @instance='*']/ .... button"
??

User avatar
Support Team
Site Admin
Site Admin
Posts: 12145
Joined: Fri Jul 07, 2006 4:30 pm
Location: Houston, Texas, USA
Contact:

Re: Finding xpath dynamically or on the fly ...

Post by Support Team » Tue May 29, 2012 1:24 pm

Hi,

I am not sure I completely got it, maybe you can give us another example of what you want to accomplish?
You can get the instance during runtime with the following code:
formMicrosoft_Excel___Book1.FormMicrosoft_Excel___Book1.Element.GetAttributeValue("Instance")
and you can also use the following RxPath which will match each of your Excel instances: "/form[@processname='EXCEL' and @class='XLMAIN' and @instance~'.']".
You can also search for all running Excel instances:
IList<Ranorex.Form> forms = Host.Local.Find<Ranorex.Form>("form[@processname='EXCEL']");
      
      foreach(Ranorex.Form form in forms){
        Report.Info("Instance: "+form.Element.GetAttributeValue("Instance"));
      }
I hope this will help you solve your problem.

Regards,
Markus
Ranorex Support Team

AppTester
Posts: 20
Joined: Thu Sep 29, 2011 12:11 am

Re: Finding xpath dynamically or on the fly ...

Post by AppTester » Tue May 29, 2012 6:44 pm

I guess my question got mixed up with the Excel example. The info you provided is great, and helps for finding different instances of an application.

But the real question is simply, can I get the xpath of a UI control during run time?

So, let's say I have an application called ABCTimeSheet. Let say ABCTimeSheet has a button called "Get Info". The xpath for it would be:

Code: Select all

/form[@controlname='frmABCTimeSheet']/button[@controlname='btnGetInfo']
Also, lets say I have a class call MyRepository where I implement this:

Code: Select all

        public static Ranorex.Button btnGetInfo
    	{    
        	get
    		{
    			Adapter.DefaultSearchTimeout = 2000;
		    	Ranorex.Button btnGetInfo = "/form[@controlname='frmABCTimeSheet']/button[@controlname='btnGetInfo']";
	    		return btnGetInfo;                   
    		} 
    	}
And in another class I create the UI object and click the button like this:

Code: Select all

Ranorex.Button btnGetInfo = MyRepo.btnGetInfo;
         btnGetInfo.Click();
My question is, in the second chunk of code, it there a way I can get the xpath dynamically (during run time) with a method such as getPath(), instead of having to hard code the xpath?

If in the future the developer changes the UI (let's say renames the button), the hard coded xpath won't work. So that's why getting the xpath dynamically would be better in the example given above.

Please help.

User avatar
Ciege
Posts: 1336
Joined: Thu Oct 16, 2008 6:46 pm
Location: Arizona, USA

Re: Finding xpath dynamically or on the fly ...

Post by Ciege » Tue May 29, 2012 7:07 pm

Assuming, as you say, the developer may change the button text, you would need to have an attribute that doesn't change, such as the internal control name of the button... Once you know that attribute you can just search for your button using that attribute yourself to get the xPath...

Something like this...

Code: Select all

Ranorex.Button MYbutton = RanorexFormName.FindSingle(".//button[@controlname='" + PushButtonName + "' or @text='" + PushButtonName + "' or @automationid='" + PushButtonName + "']", 60000);
In the above, I have this code in a method that finds and clicks a pushbutton (this can be done for most any object). I pass in the form that I want to search and the controlname of the button. However, with the way my find is written, I can also pass in the text of the button or the AutomationID of the button (if your AUT uses the AutomationID attribute).
If this or any response has helped you, please reply to the thread stating that it worked so other people with a similar issue will know how you fixed your issue!

Ciege...

AppTester
Posts: 20
Joined: Thu Sep 29, 2011 12:11 am

Re: Finding xpath dynamically or on the fly ...

Post by AppTester » Tue May 29, 2012 11:33 pm

What does PushButtonName refer to? What attribute of the button is it?

Also, RanorexFormName does not auto appear. In other words, it does not compile when I type it in Ranorex. Do I need to add a using directive?

To reiterate, I DON'T want to hard code any values.

What I need is something like this if possible:

Code: Select all

Ranorex.Button myButton = GetPath(application, buttonName);
I'm thinking that buttonName could be the object's accessiblename.

Is this possible?

User avatar
Ciege
Posts: 1336
Joined: Thu Oct 16, 2008 6:46 pm
Location: Arizona, USA

Re: Finding xpath dynamically or on the fly ...

Post by Ciege » Tue May 29, 2012 11:43 pm

Tyr spying on a button with RanorexSpy...

In the snippet I posted,
PushButtonName = a variable that holds the button name I happen to want to search for
RanorexFormName = a variable that holds the form name that I want to search on for the button

This code, placed in a method that accepts 2 variables (RanorexFormName & PushButtonName ) would search the user requested form for the user requested button... Absolutely nothing hard coded...
If this or any response has helped you, please reply to the thread stating that it worked so other people with a similar issue will know how you fixed your issue!

Ciege...

AppTester
Posts: 20
Joined: Thu Sep 29, 2011 12:11 am

Re: Finding xpath dynamically or on the fly ...

Post by AppTester » Wed May 30, 2012 6:50 pm

Hi Ciege, the path I would like to ultimately get dynamically (at run time) is:

Code: Select all

/form[@processname='EXCEL']/element[@controlname='']/element/element[@controlname='_tabControl']/element/element/element[@controlname='_gbForwardPrices']/element[@controlname='_btnGenerate']/button[@accessiblename='Generate']
Trying this code does not work (error: path not found):

Code: Select all

string PushButtonName = "_btnGenerate";

			Ranorex.Form RanorexFormName = "form[@processname='EXCEL']";
			Ranorex.Button cbxMarket = RanorexFormName.FindSingle(".//button[@controlname='" + PushButtonName + "' or @text='" + PushButtonName + "' or @automationid='" + PushButtonName + "']", 2000);
Also, the problem is that you can see I'm hard coding the variables value. Whether I'm doing it this way or passing the value to a method, it still requires knowing details of the path before hand.

What I need is a way of getting the path (or as much of its details as possible) at runtime. So if the details of the path change (with the new iteration of the software), the xpath will not be out of date and the test won't break.

Basically, I would like to programmatically implement whatever spy is doing to get the xpath, so I don't have to use spy to manually update hundreds of paths each time.

It's really important that I get a solution to this issue. Site Admin or anyone else, please feel free to weigh in if you have other suggestions. Thanks everyone.

User avatar
artur_gadomski
Posts: 207
Joined: Mon Jul 19, 2010 6:55 am
Location: Copenhagen, Denmark
Contact:

Re: Finding xpath dynamically or on the fly ...

Post by artur_gadomski » Thu May 31, 2012 10:26 am

You always need to know something beforehand. It might be a text on the button or the automation id of the button or something else but it's always something. If iteration 1 used button labeled 'New' for something and Iteration 2 has changed text and automation id of this button to 'Add' I can't possibly see how any test would be able to continue. Changes in app break (some even say they should break) tests that were made for this app. Of course you can design your path in a more robust way. Ciege's path tries to find a button based on text, control name or automation id if these things don't change then it will work regardless on where this button is or what other properties have changed..

AppTester
Posts: 20
Joined: Thu Sep 29, 2011 12:11 am

Re: Finding xpath dynamically or on the fly ...

Post by AppTester » Thu May 31, 2012 6:37 pm

What I know before hand is that name of the application (Excel. It is an Excel add in) and the area where the buttons are (in a container).

Okay, let me simplify the problem:

When I manually use spy, it gets the path for me. Then I add the path to the project either in my code or to the repository.

What I need is to find a way to programmatically get the path during run time. So, whatever spy is doing to get the path, can I do that as well?

Something like:

String[] paths = Host.Excel.Container.GetButtonPaths()

?????

User avatar
Ciege
Posts: 1336
Joined: Thu Oct 16, 2008 6:46 pm
Location: Arizona, USA

Re: Finding xpath dynamically or on the fly ...

Post by Ciege » Thu May 31, 2012 6:53 pm

But you are still doing something manually with spy. You are starting spy, moving the cursor to the button you want to examine and hitting the hotkey to get the path. You are still interacting manually with the AUT, nothing is being done automatically for you...

If you don't want to follow the suggestions given thus far, I suppose you can write a method that just finds an iList of all buttons within your known container, parse out the button you want then assign that xpath to a Ranorex button variable...
If this or any response has helped you, please reply to the thread stating that it worked so other people with a similar issue will know how you fixed your issue!

Ciege...

AppTester
Posts: 20
Joined: Thu Sep 29, 2011 12:11 am

Re: Finding xpath dynamically or on the fly ...

Post by AppTester » Thu May 31, 2012 8:52 pm

Ciege wrote:But you are still doing something manually with spy. You are starting spy, moving the cursor to the button you want to examine and hitting the hotkey to get the path. You are still interacting manually with the AUT, nothing is being done automatically for you...
No, what I want is to do what you described automatically, at runtime. The functionality that spy is capable of -- searching and finding paths -- is what I want my code to do. This way I can get the most current paths at runtime and not have to manually update paths.

I will try to implement this method:

- finds an iList of all buttons within your known container
- parse out the button you want
- assign that xpath to a Ranorex button variable

I'll let you know how it goes.

User avatar
Support Team
Site Admin
Site Admin
Posts: 12145
Joined: Fri Jul 07, 2006 4:30 pm
Location: Houston, Texas, USA
Contact:

Re: Finding xpath dynamically or on the fly ...

Post by Support Team » Fri Jun 01, 2012 7:21 am

Hi,

The thing I don't really understand is why do you want to assign the RxPath of a found button to a new button?
If you parsed out the button you want you already have the specific button and the adapter includes the full RxPath of it.
You can get get it with the GetPath method:
yourAdapter.GetPath(PathBuildMode.Simple)
Regards,
Markus
Ranorex Support Team