Frequently Asked Questions

1. What is the advantage of CUITe over Coded UI Test?

CUITe is not a replacement to Coded UI Test, but an enhancement as its name implies. But there are several things that CUITe does differently. For instance, the UI object hierarchy. Below is a sample UI object hierarchy as recorded by the Coded UI Test's built-in recorder. You can see the actual object in question sits at the 7th level.
SilverlightEdit uITextBoxBusinessDomaiEdit =
 this.UISearchWindowsInterneWindow.UISearchDocument.UISilverlightControlHoPane.UIItemCustom.UIMainPageMainPage.UIItemWindow.UITextBoxBusinessDomaiEdit;
uITextBoxBusinessDomaiEdit.Text = this.RecordedMethod1Params.UITextBoxBusinessDomaiEditText;
What CUITe does is to get rid of the objects between the top-most and the actual object in question from the hierarchy. It binds the object in question (the control that the automation wants to interact with) to the top-most container, where by giving a very logical representation. The code is a lot more readable and maintainable.
pgSearch.txtBusinessDomain.SetText("Sample Business Domain");
Applications that are under development undergo drastic changes, and object hierarchy is something that changes too often. As CUITe does not depend upon it, your test cases are not impacted. One prerequisite though, is that the objects (that you need to interact through automation) should have uniquely identifiable attributes. This may look like a restriction, but CUITe's philosophy is different.

2. How does CUITe manage to reduce code to less than 5% as opposed to traditional Coded UI Test recorded code?

For this you need to understand CUITe's philosophy.
Automation is not about just getting test cases automated. For any automation effort to be called successful, it should be readable, maintainable, resilient and robust.

It is because of the above reasons the traditional Coded UI Test recorder is dumped in CUITe.
Below is the sample code for a html hyperlink recorded using Coded UI Test recorder. Though this object has an 'id' which is an uniquely identifiable attribute, it records all other attributes as well, just in case 'id' changed. The idea is to record as many attributes of an object as possible, so that even if some attributes change, the object will still have (hopefully) a uniquely identifiable set of attributes.
        public HtmlHyperlink UIMSUserHyperlink
        {
            get
            {
                if ((this.mUIMSUserHyperlink == null))
                {
                    this.mUIMSUserHyperlink = new HtmlHyperlink(this);
                    #region Search Criteria
                    this.mUIMSUserHyperlink.SearchProperties[HtmlHyperlink.PropertyNames.Id] = "realm_Corporate";
                    this.mUIMSUserHyperlink.SearchProperties[HtmlHyperlink.PropertyNames.Name] = null;
                    this.mUIMSUserHyperlink.SearchProperties[HtmlHyperlink.PropertyNames.Target] = null;
                    this.mUIMSUserHyperlink.SearchProperties[HtmlHyperlink.PropertyNames.InnerText] = "MS User ";
                    this.mUIMSUserHyperlink.FilterProperties[HtmlHyperlink.PropertyNames.AbsolutePath] = "OnClickClientRealm(%22Corporate%22)";
                    this.mUIMSUserHyperlink.FilterProperties[HtmlHyperlink.PropertyNames.Title] = "MS User";
                    this.mUIMSUserHyperlink.FilterProperties[HtmlHyperlink.PropertyNames.Href] = "javascript:OnClickClientRealm(\"Corporate\")";
                    this.mUIMSUserHyperlink.FilterProperties[HtmlHyperlink.PropertyNames.Class] = "Name";
                    this.mUIMSUserHyperlink.FilterProperties[HtmlHyperlink.PropertyNames.ControlDefinition] = "id=realm_Corporate class=Name title=\"MS ";
                    this.mUIMSUserHyperlink.FilterProperties[HtmlHyperlink.PropertyNames.TagInstance] = "4";
                    this.mUIMSUserHyperlink.WindowTitles.Add("Select Client Realm");
                    #endregion
                }
                return this.mUIMSUserHyperlink;
            }
        } 
Here is where CUITe has a different way of seeing things. Lack of uniquely identifiable attribute(s) is something that should be addressed at the development phase itself. Development best practices should include points to be ensured to have an 'automation friendly' application. If an object has an 'id' CUITe ignores all other attributes, if 'id' is not there, it captures other attributes that will help identify the object. CUITe object repository code for the same above hyperlink will look like:
public CUITe_HtmlHyperlink lnkMSUser = new CUITe_HtmlHyperlink("Id=realm_Corporate");
CUITe_HtmlHyperlink is a wrapper class of HtmlHyperlink.

3. What are the advantages of CUITe Object Repository over the Coded UI Test UIMap?

CUITe allows you to define a much simpler Object Repository (== UIMap). Each page/window will be defined in a separate class file, and each UI control definition will be just a one liner. You can move common controls to a parent class which increases maintainability. You can also categorize the page/window definition classes into different folders as you deem fit.

The test code is readable and maintainable. Handling a Search Results table is more logical as you can see below.
pgSATHome.lnkFindApplication.Click();
FindApplication pgFindApplication = CUITe_BrowserWindow.GetBrowserWindow<FindApplication>();
pgFindApplication.txtApplicationNameToSearch.SetText("Test App by Automation");
pgFindApplication.btnSearch.Click();
pgFindApplication.tblApplicationsSearchResult.FindRowAndDoubleClick(3, "Active", CUITe_HtmlTableSearchOptions.NormalTight);
In Coded UI Test, UIMap.Designer.cs is the core class file where all page/window/object definitions, recorded methods, assert methods and parameter classes are kept. This makes it very huge and unmaintainable. Although there is an option to have multiple UIMaps, it was not convincing for me.

I wanted a much simpler, granular, organized way of doing the same thing. For this I first came up with the concept of Object Repository. It is a folder placed directly under the Test project. Each page/widow in the application will have a separate class (inherited from CUITe_BrowserWindow) file containing the object definitions. You can have sub folders or sub-sub folders (any level is permissible) under Object Repository based on your requirement (say for example, each module in your application can be a sub folder and each feature can be a sub-sub folder and so on). This helps you in arranging the object definitions in a manageable way.

The greatest benefit is inheritance. You can move all common objects (definitions) out of the classes to a parent class. For example, if all pages of your application has a common header and footer, you can move those object definitions to a 'Common' class, and get all other classes to inherit from it. Each of your module can have a 'Common' class (module1Common, module2Common etc.), which in turn can inherit from the base 'Common' class. You can have methods too in these classes which you think are re-usable and are related to the page/window definition. For example, the 'CreateEmployee' page definition class can have create employee method.



Object repository is super useful, if you can put some amount of thinking and planning.

You can also get things done without Object Repository classes, see Ability to interact with controls without creating an ObjectRepository class.

4. What do you mean by 'CUITe treats Table as a Table'?

When you record an action of selecting a row in a table, Coded UI Test records the object/control in the cell or the cell itself. This could create problems if the data in the table changes. To have a more maintainable code in such scenarios, you need to be able to treat table as a table. See the CUITe code below. Here, we are finding the row by the text inside a particular column, and then clicking it. Readable, maintainable and logical.

int iRow1 = pgSponsorshipProperties.tblSSGsToAssociateToASGs.FindRow(1, "SSG", CUITe_HtmlTableSearchOptions.Greedy);
pgSponsorshipProperties.tblSSGsToAssociateToASGs.FindCellAndClick(iRow1, 1);
pgSponsorshipProperties.btnAssociateSSGsToASGs.Click();
pgSponsorshipProperties.btnApply.Click();

5. What is so great about GetEmbeddedCheckBox() method in the CUITe_HtmlTable wrapper class?

Web applications often have search results (or data to be very generic) displayed in a table, each row having a checkbox to enable selection for read/edit/delete operations. As the data in the table is dynamic, the checkboxes are also rendered dynamically. They will have a dynamically generated 'id' (or another unique identifier attribute). If your test case is about selecting a particular row in the table and pressing 'Remove' button, Coded UI Test will end-up recording the checkbox directly, without really worrying about the logical flow. The search properties of the checkbox will be hard-coded in the UIMap, and the moment the data changes the test cases are gonna fail. This kind of recorded code is very difficult to maintain, and is less readable.

CUITe does things differently here. See the code below written for a web application. This will work fine even if the data changes or developer changes the way he generates the 'id' or unique identifier attribute for the checkbox.
int iRow2 = pgSponsorshipProperties.tblAssociatedSSGsToASGs.FindRow(0, "SSG", CUITe_HtmlTableSearchOptions.Greedy);
pgSponsorshipProperties.tblAssociatedSSGsToASGs.GetEmbeddedCheckBox(iRow2, 0).Check();
pgSponsorshipProperties.btnRemoveAssociateSSGsToASGs.Click();
pgSponsorshipProperties.btnApply.Click();

6. How much value does JavaScript support give to web automation? Can you give some examples?

You can insert javascript code into to the DOM context and evaluate it at runtime. You can also invoke methods in the DOM.
JS.jpg

7. How to setup and use CUITe?

Please refer the Quick Start guide.

8. Does CUITe ObjectRecorder work for Silverlight?
No, at this point of time. I do have plans to add support for Silverlight in the ObjectRecorder, but it may take some time. Till such time you may use Silverlight spy 4 or work with the xaml files (get it from the developer).

Last edited Oct 14, 2011 at 3:10 PM by sureba, version 32

Comments

kensou28 Apr 25, 2013 at 10:51 AM 
nice FAQ, help me great