How Selenium Page Object Code Generator helped us bring down the coding time from 4.5 hours to less than 5 minutes for a single page object!!
How it started:
Back in 2012 we used to have separate teams for manual and automation testing. Automation team comprised of 2-3 people, who were working on customized hybrid framework in Selenium whereas the manual testing team was of approx. 25-30 people. This dedicated automation team used to cater to the automation needs for all Info Edge sites like Naukri.com, NaukriGulf.com, 99acres.com, Jeevansathi.com & Shiksha.com. The automation work used to happen then for very limited scope and very late in the release cycle. In 2013 we brought in a paradigm shift and trained the entire testing team in Selenium and embarked on a journey to have a team which was fully equipped in doing testing entirely, which meant both manual and automation testing. As the automation team grew suddenly from 2 to 25 so did the need for bringing in processes like Coding standards, Folder structure, Code management and Frameworks.
We then finalized our framework architecture design – POM (Page Object Model) with TestNG and XSLT for custom report generation and started implementing the same in our team.
Although POM brought with it host of advantages like standardization, maintainability, clarity, scalability and robustness, it needed too much of mundane and repetitive coding effort in creating page objects with locator definitions and common functions for each locator.
Just to understand the gravity of this downside let us do effort estimation for a single form:
Say we have a registration page consisting of 13 textboxes, 5 dropdowns, 2 check boxes, 3 links and 1 button. Then the total number of methods required for creating page object class would be as follows:
WebElement | Methods | No of methods | No of elements on Form | Total Methods |
Effort
(3min/Method) |
Textbox | Fill, Click, GetText, Clear | 4 | 13 | 52 |
156
|
DropDown | Select, DeSelect, GetSelectedValue, GetSelectedID | 4 | 5 | 20 |
60
|
Checkbox | Check, UnCheck, IsChecked | 3 | 2 | 6 |
18
|
Radio button | Select, GetSelectedValue | 2 | 0 | 0 |
0
|
Link | Click, GetLinkText | 2 | 3 | 6 |
18
|
Button | Click | 1 | 1 | 1 |
3
|
WebElement | Click, GetElementText | 2 | 0 | 0 |
0
|
Total Methods | 85 |
255 minutes
|
Thus the total effort required to write code for a single page object for the first time was approximately 255 minutes which is a whopping 4.5 hours !!
Solution: We came up with the idea of creating Automated Code generator for Page Objects. Knowing the standard list of functions associated and needed with each HTML element type we went ahead and created the following code generator. And with this within 2-4 minutes anyone and everyone could generate all the code needed to get him started with any page object class.
So to take an example:
We wanted to generate code for a search form page comprising of keyword, location textbox and experience and salary drop downs & a search button
publicclassQSB_Naukri {
WebDriver driver;
GenericFunctions generic;
finalstaticpublicString Keywords_Txt= “//div[@id=’skill’]//input[1]”;
finalstaticpublicString Location_Txt= “//div[@id=’location’]//input[1]”;
finalstaticpublicString Experience_DD= “//div[@id=’exp_dd’]/div/input[1]”;
finalstaticpublicString Salary_DD= “//div[@id=’salary_dd’]/div/input[1]”;
finalstaticpublicString Search_Btn= “//button[text()=’Search ‘]”;
}
Step 1 for Code generation:
-
Write xpaths following defined coding guidelines for each element type (like “_Txt” for text box, “_DD” for dropdown, “_Btn” for button etc)
final static public String Keywords_Txt = “//div[@id=’skill’]//input[1]”;
finalstaticpublicString Location_Txt= “//div[@id=’location’]//input[1]”;
finalstaticpublicString Location_Txt= “//div[@id=’location’]//input[1]”;
finalstaticpublicString Experience_DD= “//div[@id=’exp_dd’]/div/input[1]”;
finalstaticpublicString Salary_DD= “//div[@id=’salary_dd’]/div/input[1]”;
finalstaticpublicString Search_Btn= “//button[text()=’Search ‘]”;
-
Fetch the variables declared in the class
-
Traverse through each variable to know its name
-
Check the type of web object[ by using step1]
-
Generate Code
//Create object for the class that we want to generate code
QSB_Naukri p1 =new QSB_Naukri ();
// Traverse through each xpath variable
for(Field field : p1.getClass().getDeclaredFields()) {
String xpathdet = field.getName();
//check condition to know type of object and generate code
if(xpathdet.endsWith(“_Txt”)){
//generate code like this
BufferedWriter out= = new BufferedWriter(new FileWriter(“Path for the generated code”, true));
//generate code like this
BufferedWriter out= = new BufferedWriter(new FileWriter(“Path for the generated code”, true));
out.newLine();
out.write(“public void Fill_”+label_name+“_Txt(String inputdata){“);
out.newLine();
out.newLine();
out.write(“if(inputdata.trim().length()==0)return;”);
out.newLine();
out.write(“try{“);
out.newLine();
out.write(“driver.findElement(By.xpath(“+xpathdet+“)).clear();”);
out.newLine();
out.write(“driver.findElement(By.xpath(“+xpathdet+“)).sendKeys(inputdata);”);
out.newLine();
out.write(“}catch(Exception e){“);
out.newLine();
out.write(“generic.GoToSleep(sleepTime);”);
out.newLine();
out.write(“driver.findElement(By.xpath(“+xpathdet+“)).clear();”);
out.newLine(); out.write(“driver.findElement(By.xpath(“+xpathdet+“)).sendKeys(inputdata);”);
out.newLine();
out.write(“}”);
out.newLine();
out.write(“}”);
out.newLine();
}
}
Generated Code:
}
Generated Code:
WebDriver driver;
GenericFunctions generic;
public int sleepTime=4000;
public voidFill_Keywords_Txt(String inputdata){
if(inputdata.trim().length()==0)return;
try{
driver.findElement(By.xpath(Keywords_Txt)).clear();
driver.findElement(By.xpath(Keywords_Txt)).sendKeys(inputdata);
}catch(Exception e){
generic.GoToSleep(sleepTime);
driver.findElement(By.xpath(Keywords_Txt)).clear();
driver.findElement(By.xpath(Keywords_Txt)).sendKeys(inputdata);
}
}
public voidClear_Keywords_Txt(){
try{
driver.findElement(By.xpath(Keywords_Txt)).clear();
}catch(Exception e){
generic.GoToSleep(sleepTime);
driver.findElement(By.xpath(Keywords_Txt)).clear();
}
}
publicString GetText_Keywords_Txt(){
try{
returndriver.findElement(By.xpath(Keywords_Txt)).getAttribute(“value”);
returndriver.findElement(By.xpath(Keywords_Txt)).getAttribute(“value”);
}catch(Exception e){
generic.GoToSleep(sleepTime);
returndriver.findElement(By.xpath(Keywords_Txt)).getAttribute(“value”);
returndriver.findElement(By.xpath(Keywords_Txt)).getAttribute(“value”);
}
}
public voidFill_Location_Txt(String inputdata){
public voidFill_Location_Txt(String inputdata){
if(inputdata.trim().length()==0)return;
try{
driver.findElement(By.xpath(Location_Txt)).clear();
driver.findElement(By.xpath(Location_Txt)).sendKeys(inputdata);
}catch(Exception e){
generic.GoToSleep(sleepTime);
driver.findElement(By.xpath(Location_Txt)).clear();
driver.findElement(By.xpath(Location_Txt)).sendKeys(inputdata);
}
}
public voidClear_Location_Txt(){
public voidClear_Location_Txt(){
try{
driver.findElement(By.xpath(Location_Txt)).clear();
}catch(Exception e){
generic.GoToSleep(sleepTime);
driver.findElement(By.xpath(Location_Txt)).clear();
}
}
public voidClick_Location_Txt(){
try{
driver.findElement(By.xpath(Location_Txt)).click();
}catch(Exception e){
generic.GoToSleep(sleepTime);
driver.findElement(By.xpath(Location_Txt)).click();
}
}
publicString GetText_Location_Txt(){
try{
returndriver.findElement(By.xpath(Location_Txt)).getAttribute(“value”);
returndriver.findElement(By.xpath(Location_Txt)).getAttribute(“value”);
}catch(Exception e){
generic.GoToSleep(sleepTime);
returndriver.findElement(By.xpath(Location_Txt)).getAttribute(“value”);
}
}
publicvoidSelect_Experience_DD(String inputdata){
if(inputdata.trim().length()==0)return;
generic.Click(Experience_DD);
generic.GoToSleep(2000);
generic.Click(“//div[@id=’exp_dd’]//ul//li[text()='”+inputdata+“‘]”);
}
publicvoidDeSelect_Experience_DD(String inputdata){
if(inputdata.trim().length()==0)return;
try{
newSelect (driver.findElement(By.xpath(Experience_DD))).deselectByVisibleText(inputdata);
newSelect (driver.findElement(By.xpath(Experience_DD))).deselectByVisibleText(inputdata);
}catch(Exception e){
generic.GoToSleep(sleepTime);
newSelect (driver.findElement(By.xpath(Experience_DD))).deselectByVisibleText(inputdata);
newSelect (driver.findElement(By.xpath(Experience_DD))).deselectByVisibleText(inputdata);
}
}
publicvoidSelect_Salary_DD(String inputdata){
publicvoidSelect_Salary_DD(String inputdata){
if(inputdata.trim().length()==0)return;
generic.Click(Salary_DD);
generic.GoToSleep(2000);
generic.Click(“//div[@id=’salary_dd’]//ul//li[text()='”+inputdata+“‘]”);
}
publicvoidDeSelect_Salary_DD(String inputdata){
try{
newSelect (driver.findElement(By.xpath(Salary_DD))).deselectByVisibleText(inputdata);
newSelect (driver.findElement(By.xpath(Salary_DD))).deselectByVisibleText(inputdata);
}catch(Exception e){
generic.GoToSleep(sleepTime);
newSelect (driver.findElement(By.xpath(Salary_DD))).deselectByVisibleText(inputdata);
newSelect (driver.findElement(By.xpath(Salary_DD))).deselectByVisibleText(inputdata);
}
}
publicvoidClick_Search_Btn(){
try{
driver.findElement(By.xpath(Search_Btn)).click();
}catch(Exception e){
generic.GoToSleep(sleepTime);
driver.findElement(By.xpath(Search_Btn)).click();
}
}
Viola, we have reduced the effort from 4.5 hours to 2-4 minutes!!
We have open sourced this project and same can be available from SeleniumCodeGenerator
Related Posts
Posted in Automation, Automation Testing
Thanks for your informative post on selenium automation testing tool. Your article helped me a lot in understanding the future of automation testing tool and its career prospects. Selenium Training
Software testing industry offer huge career opportunity for talented professionals. software testing training in Chennai
Excellent post!!! Selenium automation testing tool makes your software validation process lot simpler. Keep on updating your blog with such awesome information. Selenium Training in Chennai | Selenium Course in Chennai | Selenium training institute in Chennai
Sure Jesica, soon we will be updating this blog with many more features.
Nice information about the load testing!!! I prefer Loadrunner automation testing tool to validate the performance of software application/system under actual load. Loadrunner Course in Chennai | Loadrunner training institute in Chennai
Hi,
I tried to use this too and i see all the loctors it created are css based. Is there a way to get this tool create locators using name or Link_Name or ID etc.
Thanks
Vams
Hi Vams,
Here we are using xpath locator(not css), if you want to use other locators like id, name etc., please follow
1. Use ‘By’ to locate elements as shown below
By username_Txt =By.id(“username”);
By password_Txt =By.name(“password”);
By login_Btn =By.id(“loginbtn”);
2. Customize the above page object code generator so that it will support ‘By’ instead of xpath
Hope this will help you!!
Regards
Omkar Kesa
Thanks for the cool post on selenium object code
Here’s from my own code:
Window.setTimeout executes just when a browser is idle.
Therefore contacting the operate recursively (42 occasions) may just take 100ms if there’s no task in the browser and much more if the browser is busy performing something else.