Saturday, December 30, 2017
UI Elements All about it!
UI Elements All about it!
What is UI-Element?
UI-Element is selenium�s answer to object repository. Those of us who have worked with test automation tools like QTP and WinRunner know what they are. Just to recap object repositories or GUI-Maps are map files where GUI object references are stored. These typically allow you to create logical entities and map them to GUI elements present in your test application. Now in your test script wherever there is a need to refer to a GUI element you can do so using its logical name given in the map file. This allows us to have logical names for ui objects instead of literal locator strings.
UI-Element is supported as a user extension in Selenium IDE and Selenium-RC. Haw-Bin Chai is the creator of this cool feature.The complete documentation of UI-Elements is available here . I know the official doc is a little overwhelming when you read it for the first time. But dont worry we would only be needing a very small part of the stuff that is in there.
Why do we need it?
* Readability: You have semantically meaningful names of elements in your test script rather than having the locators themselves that don�t make much sense. The test script becomes readable and comprehendible to a non-technical person as well.
* Maintainability
+ Single point of update: If the definition of a ui-element changes than you need to make changes at just one central location i.e. in your map file. Against this if you are using literal locators in your test script you would have to edit every instance of that element in your script. This is usually very tedious and error prone.
+ Error checking: ui-map file is JavaScript file that will alert you if there were any syntactical mistakes like ill-formed regular expressions etc.
Below you can see a two versions of a test scenario recorded using IDE. The scenario involves searching for the word wikipedia in google and then searching for the word selenium in the wikipedia search. There are a few verify and waitFor commands thrown in just to make the whole thing look good. Now the first one is without the usage of UI-Elements, just the plain recording and the next one uses UI-Elements. Notice how the script becomes a lot more readable when using UI-Elements.
Google-wiki script without using UI-Elements
Command | Target | Value |
open | http://www.google.co.in/ | |
verifyElementPresent | logo | |
type | q | wikipedia |
click | btnG | |
waitForElementPresent | nqsbq | |
verifyElementPresent | nqsbq | |
type | nqsbq | selenium |
click | btnGNS | |
waitForElementPresent | link=Selenium (software) - Wikipedia, the free encyclopedia | |
verifyElementPresent | link=Selenium (software) - Wikipedia, the free encyclopedia | |
click | link=Selenium (software) - Wikipedia, the free encyclopedia | |
waitForElementPresent | //div[@id=p-logo]/a | |
verifyTitle | Selenium (software) - Wikipedia, the free encyclopedia | |
verifyElementPresent | //div[@id=p-logo]/a | |
Same script with UI-Elements
Command | Target | Value |
open | http://www.google.co.in/ | |
verifyElementPresent | ui=googleSearch_page::theBigGoogleLogo() | |
type | ui=googleSearch_page::search_Textbox() | wikipedia |
click | ui=googleSearch_page::search_button() | |
waitForElementPresent | ui=googleSearch_page::searchwikipedia_textbox() | |
verifyElementPresent | ui=googleSearch_page::searchwikipedia_textbox() | |
type | ui=googleSearch_page::searchwikipedia_textbox() | selenium |
click | ui=googleSearch_page::searchwikipedia_button() | |
waitForElementPresent | ui=googleSearch_page::seleniumSearchResult_Link() | |
verifyElementPresent | ui=googleSearch_page::seleniumSearchResult_Link() | |
clickAndWait | ui=googleSearch_page::seleniumSearchResult_Link() | |
waitForElementPresent | ui=wikipediaArticle_page::wikipediaGlobe_image() | |
verifyTitle | Selenium (software) - Wikipedia, the free encyclopedia | |
verifyElementPresent | ui=wikipediaArticle_page::wikipediaGlobe_image() | |
The UI-Element map file used to for this script is as follows:
var myMap = new UIMap();
myMap.addPageset({
name: googleSearch_page
, description: google main search page
, pathRegexp: .*
});
myMap.addElement(googleSearch_page, {
name: theBigGoogleLogo
, description: the Google logo visible on the main google search page
, locator: "logo"
}
);
myMap.addElement(googleSearch_page, {
name: search_Textbox
, description: the Google search textbox on google search page
, locator: "q"
}
);
myMap.addElement(googleSearch_page, {
name: search_button
, description: the Google search button with "Google Search" label on google search page
, locator: "btnG"
}
);
myMap.addElement(googleSearch_page, {
name: firstSearchResultItem_Link
, description: the first item in the search result list
, locator: "//ol[@id=rso]/li[1]/h3/a/em"
}
);
myMap.addElement(googleSearch_page, {
name: searchwikipedia_textbox
, description: search wikipedia text box below the google search result item
, locator: "nqsbq"
}
);
myMap.addElement(googleSearch_page, {
name: searchwikipedia_button
, description: Search Wikipedia.org button
, locator: "btnGNS"
}
);
myMap.addElement(googleSearch_page, {
name: seleniumSearchResult_Link
, description: search result link to selenium article in wikipedia
, locator:"link=Selenium (software) - Wikipedia, the free encyclopedia"
}
);
myMap.addElement(googleSearch_page, {
name: wikipediaSeleniumPage_title
, description: Title of th wiki page for selenium
, locator:"Selenium (software) - Wikipedia, the free encyclopedia"
}
);
myMap.addPageset({
name: wikipediaArticle_page
, description: wikipedia
, pathRegexp: wiki/Selenium.*
});
myMap.addElement(wikipediaArticle_page, {
name: wikipediaGlobe_image
, description: Wikipedia, the free encyclopedia globe image
, locator:"//div[@id=p-logo]/a"
}
);
This UI-MAP file has to be created manually. It looks quite complex but believe me it becomes a lot easier ones you start using it regularly. This map file is a JavaScript file with extention .js and has to be attached to Selenium IDE from Options->Options->Selenium Core Extentions. Try this example out yourself. Just copy the entire html table above and paste it into the IDE (except the header row). Similarly copy ui-map file into notepad and save it as uiMapGoogle.js. Now attach this file as a user extension in IDE options. You will be able to run the ui-element version of the script at this point. Also for any recording you do on the element mentioned in the map file you will see UI-Element based locators recorded in the IDE window. Also remember that after making any changes the map file the changes will take effect only after you close-reopen the IDE window.
Why UI-Element and why not .properties file?
There are many advantages to using the UI-Elements approach
1) Selenium IDE supports UI-Elements. This means IDE will record your scripts and use UI-Elements in place of literal locator values if you provide it with UI-Elements map file for the application that you are recording on. After recording your scripts in IDE the scripts can easily be ported to the Selenium-RC environment in a language of your liking. IDE does not support any other mapping approach.
2) A map file created using UI-Elements approach will be much easier to maintain in the long run because it will mind its integrity on its own. A JavaScript file will not allow duplicate entries or malformed regular expressions. A flat file like a �.properties� file will not have such error checking abilities.
Structure of UI-Element map file
The map file is has a 2 level hierarchy. The top level is the �Pageset� and the next level is the �element�. Think of a map file as a collection of pages with any number of elements within each page.
So first you add a pageset and then add elements within that pageset. For every elemnt there a set of mandatory properties you must add. For a pageset element name and description properties are mandatory. And for a element within a pageset name, description and locator are mandatory properties.
For example in the ui-map below googleSearch_page is the pageset element and theBigGoogleLogo is the element within googleSearch_page. Notice in the addElement method how googleSearch_page is the first parameter.
myMap.addPageset({
name: googleSearch_page
, description: google main search page
, pathRegexp: .*
});
myMap.addElement(googleSearch_page, {
name: theBigGoogleLogo
, description: the Google logo visible on the main google search page
, locator: "logo"
}
);
The property name is the logical name of the element, description is just description of what the element is all about and locator is locator of that element. All ui maps must begin with the below statement.
var myMap = new UIMap();
The �pathRegexp� property defined with the pageset element signifies which pages (paths after domain excluding cgi e.g abc/789 in www.google.com/abc/789 ?lang=en_US) are to be matched with this pageset element.
Read the documentation of UI-Element for understanding other properties that can be used with pageset item and elements within it. The properties covered in this post are the most basic ones and should be sufficient for majority of cases.