Thursday, 11 December 2014

Test Automation in Agile Methodology: A confusing hot cake !!

Agile is one of trend setter in market, most of the product based firms are using Agile Methodology. Whether to do test automation in agile project or not, is one of widely discussed but confusing hot cake. When we think about agile, the first thing comes to mind is flexibility, nothing is frozen and we can make the changes as an when those are required. So in initial some iteration the product design changes frequently. Test Automation requires some sort of stability in design and layout of the application. And if the design changes the automation team needs to struggle repeatedly to maintain the automation scripts. 

We need to have a close co-operation between development team and automation team. We need to develop the automation scripts in such way that application lay out change have minimum impact on coded scripts. One of the ways can be, instead of capturing the objects in object map or repository along with parent child hierarchy, we should descriptively find and use the object with help of locators like .id, .name, .text etc. Thus if developers are not making changes in any of these properties of object and only the parent child hierarchy is getting changed because of addition or deletion of some objects in application design, still the automation script will run smoothly.

As the applications get matured and the design achieves some threshold stability, test automation starts paying you back.
Usually automation is separated from development and considered as a side activity of testing department. Sorry to say but often it is thought that anyone can do test automation using code less and script-less frameworks available in market. But automation does require programming knowledge, it does require planning. Many time teams even do not do the proof of concept and feasibility analysis before start automating the tests. That’s why many times we do not succeed in test automation.

Well planned and skill-fully developed test automation always has high probability of success.
Automation is like a mutual fund investment, if we start looking of for benefits in short term, we may or we may not succeed but if think of long term return over investment and plan it skill-fully, automation will surely pay back.

Please feel free to share your thoughts and suggestions.

Thanks and Regards,      
Anupam Kumar
er.anupamkumar@gmail.com 

http://eranupamkumar.blogspot.in/

Tuesday, 9 December 2014

How to use an external Excel Sheet as an object repository in RFT?

In my previous post, have explained about how we can find an object iteratively with some max timeout in application. In continuation will be explaining how we can use an excel sheet as an object repository for storing object properties, instead of capturing the object in object map. The object properties can be read from excel sheet and can be used to find the object in application at runtime.

We need to maintain an excel sheet as an external object repository in below format:


 In External Object Sheet we have 5 Columns namely :

1. OBJECT_NAME : The Name of the object through which it will be identified  in test scripts.
2. PropertyName1 : The first locator property name for the object through which we will be identifying the object. Generally this property is “.class”
 3. PropertyValue1: The Value for property 1.
 4. PropertyName2: The socond locator property name for the object through which we will be identifying the object. This property usually uniquely identify the object in application but not necessarily always. Generally used are : .id , .name , .text , for etc.
 5. PropertyValue2: The Value for Property 2.

Suppose this external sheet reside in below path in the project:
 SheetPath = “C://…….//ExternalObjectSheet.xls” and sheet name is “ObjectProperties” in the workbook. This information should be defined as application environment variable in the project.

We will be using Apache Poi API for accessing the excel sheets. 

We will be first try to find the object in OBJECT_NAME column and the read the corresponding property names and values for the object in respective array.

Now find the root test object as “rootObject” in the screen with the help of getRootTestObject () method.

 Now pass this rootObject along with property name and property value array to function find_object_iteratively which will return the test object  array. Return the 1st element of test object array.


public TestObject LoadObjectFromExternalObjectSheet(String ObjectName) throws Exception
                {                             
                                String SheetPath = “”; // Retrieve from Application Environment Variable of project.
                                String sheetName = ""; // Retrieve from Application Environment Variable of project.
// Create
                                Workbook dataWB;
                                String ObjRow = "";
                                String [] PropName = new String [2];
                                String [] PropValue = new String [2];
                                int ObjectFoundInSheetFlag = 0;
                                try{
                                                if(SheetPath.contains(".xlsx")){
                                                                dataWB = new XSSFWorkbook(SheetPath);
                                                }
                                                else{                                                     
                                                                InputStream inp = new FileInputStream(SheetPath);
                                                                dataWB = (Workbook) new HSSFWorkbook(new POIFSFileSystem(inp));                                                                             
                                                }
                                                Sheet sheet = null;
                                                try{
                                                                sheet = dataWB.getSheet(sheetName.toString());
                                                }
                                                catch(Exception e1){
                                                                throw new Exception("Sheet not present in the excel");
                                                }
                                                int noOfRows = sheet.getLastRowNum(); // row count of dataSheet                                                     
                                                if(noOfRows == 0){
                                                                throw new Exception("no rows present");
                                                }
                                                Row row = null;
                                                for (int i=1;i<(noOfRows+1);i++)
                                                {
                                                                row=sheet.getRow(i);
                                                               
                                                                if(row == null){
                                                                                continue;
                                                                }

                                                                try{
                                                                                ObjRow = row.getCell(findCol(sheet, "OBJECT_NAME")).toString().trim();                                                                          
                                                                }
                                                                catch(Exception e1){
                                                                                ObjRow= "";
                                                                               
                                                                }
                                                                if(ObjRow.equalsIgnoreCase(ObjectName))
                                                                {
                                                                                ObjectFoundInSheetFlag=1;
                                                                                PropName[0]=GetColumnValue(sheet,"PropertyName1",row);
                                                                                PropName[1]=GetColumnValue(sheet,"PropertyName2",row);
                                                                                //PropName[2]=GetColumnValue(sheet,"PropertyName3",row);
                                                                                PropValue[0]=GetColumnValue(sheet,"PropertyValue1",row);
                                                                                PropValue[1]=GetColumnValue(sheet,"PropertyValue2",row);
                                                                                //PropValue[2]=GetColumnValue(sheet,"PropertyValue3",row);                                                           
                                                                }
                                                }
                                                if(ObjectFoundInSheetFlag == 0)
                                                {
                                                                logTestResult ("Object:"+ObjectName+" Not found in External object File",false);
                                                                return null;
                                                }
                                                if ((PropName[0].equalsIgnoreCase(""))&&(PropName[1].equalsIgnoreCase(""))||((PropValue[0].equalsIgnoreCase(""))&&(PropValue[1].equalsIgnoreCase(""))))
                                                {
                                                                logTestResult ("Object Properties not defined in External object File for object"+ObjectName,false);
                                                                return null;
                                                }
                                                else
                                                {
                                                                RootTestObject rootObject = getRootTestObject();
                                                                TestObject [] foundObjs = find_object_iteratively (rootObject,PropName,PropValue);
                                                                return foundObjs[0];    
                                                }                                                             
                                }
                                catch(NullPointerException e){
                                                return null;
                                }
                                catch (ObjectNotFoundException e2){
                                                logTestResult ("Object not found Exception:"+e2.getMessage(),false);
                                                return null;
                                }
                                catch (FileNotFoundException e) {
                                                logTestResult ("There is no data excel file in the specified path: " + "'"+SheetPath+"'",false);
                                                throw new Exception("File Not Found");
                                }
                                catch(Exception e) {
                                                logTestResult ("Exception :"+e.getMessage()+" in keyword GetObjectFromExternalObjectSheet using object ",false);
                                                return null;
                                }                             
                }

Please feel free to share your thoughts and suggestion on the approach.

Thanks and Regards,
Anupam
er.anupamkumar@gmail.com

Sunday, 7 December 2014

Automated Test Data Validation as a Test Prerequisite

Challenges in Common Test Environment: 

Test environment plays a key role in regression testing. Generally, test bed is separate for Regression & System and Integration Testing (or any other testing). In unavoidable situations there avails the same test environment for both regression and SIT testing. The major problem that arises in those situations is the Test Data Management. Being a common environment, the test data gets modified by one team without intimation to other teams.
This affects the execution of Automated Test Scripts in the Regression Lab which results into script failure due to test data.



Automated Test Data Validation Approach:
­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­One of the possible solutions to overcome above issue is that, the testing team should verify and validate the test data as a prerequisite and refresh the data in case it is altered before starting the execution of automated scripts in the lab.
But this becomes a time consuming task and requires huge amount of manual efforts if the amount of test data is very large in numbers. This problem can be solved by automating the validation and verification process. This will reduce the manual efforts and time to prepare the test data and ensure that the test data prerequisite is met.

Steps:
1.      Identify the key test data in the test suite.  
2.      Develop an Automation Script to validate all the test data that is under use in Regression Suite in the test Environment.
3.      Run the script to Validate as Test data.
4.      Analyse the result for Valid and Invalid test data.
5.      Use the Valid Test Data for Automated Test Scripts in Regression Testing
   6.      Repeat the steps 3,4 and 5 for multiple releases. 
Key Benefits:

1.11. Reduction of Regression Test Script failures due to Test Data.
Data Validation before running the automation suite reduces the data failure percentage in the execution. This saves time and efforts in analysing the Test Data Failures.                                                              



2. Increase in Efficiency of Regression Test Suite.
Reduction in Test Data Failures enhances the test effectiveness ratio of regression suite. Thus chances of catching defects increases.




3. Reduction in Manual Effort for Validating and Preparing the Test Data.
Test Data preparation and validation requires a huge manual efforts. Automated approach reduces the manual efforts and increases the accuracy as well as efficiency.
 
4. Increase in Productivity of Regression Testing.
The overall productivity increases as execution cycle time gets improved and test effectiveness is also is increased with this approach
               






Please feel free to comment, share and reach me if case any clarifications, suggestions and any idea.

Thanks 
Anupam Kumar
er.anupamkumar@gmail.com

Wednesday, 3 December 2014

IBM RFT – Descriptive Programming – Iteratively finding object in the application with time out.

IBM RFT – Descriptive Programming – Iteratively finding object  in the application with time out.


In RFT we have waitforExistence() method to wait till the application loads and object appears, but some time if the application itself is not loaded, RFT waits for an indefinite time, and execution does not proceeds. To overcome this issue we can find the object iteratively in application considering some Timeout duration defined in Frameworks Environment Variable file.

public TestObject[] find_object_iteratively (TestObject root_object, String [] elem_attribute_name, String [] elem_attribute_value)
                {             
                                int timeout=0;
                                double sleep_time=0.1;
                                double timeout_wait= 20.0; // this is hard coded value can be retrived from environment variable file.
                                TestObject[] reqObjects = root_object.find(atDescendant(elem_attribute_name[0].toString(),elem_attribute_value[0].toString(),elem_attribute_name[1].toString(),elem_attribute_value[1].toString()), false);
                                while (reqObjects.length == 0)
                                {
                                sleep(sleep_time);
                                timeout++;
                                reqObjects = root_object.find(atDescendant(elem_attribute_name[0].toString(),elem_attribute_value[0].toString(),elem_attribute_name[1].toString(),elem_attribute_value[1].toString()), false);
                                if (timeout>=timeout_wait) {
                                                timeout=0;break;
                                }
                                }
                                if (html_element.length == 0)
                                {
                                                logTestResult ("Object with Properties :"+elem_attribute_name[0].toString()+":"+elem_attribute_value[0].toString()+","+elem_attribute_name[1].toString()+":"+elem_attribute_value[1].toString()+ " Not found in the screen",false);
                                return null;
                                }
                                else
                                {
                                                logTestResult ("Object with Properties :"+elem_attribute_name[0].toString()+":"+elem_attribute_value[0].toString()+","+elem_attribute_name[1].toString()+":"+elem_attribute_value[1].toString()+ " found in the screen",true);
                                               
                                return reqObjects;
                                }
                }

IBM RFT – Descriptive Programming – Function to kill and start the application in browser.

IBM RFT – Descriptive Programming – Function to kill and start the application in browser.


This function can be used to launch the application URL in browser. It contains “Mode” as a Flag variable which if used to decide whether to close all the browser session and launches the specified URL in a new browser, or launch the browser in without closing previously opened browser sessions. As of now have hardcoded the value of Mode variable as “regression” but can be dynamically retrieved from frameworks environment variable settings file.

public boolean launch_browser_appURL (String appURL)
{
try{
String mode = "regression"; // Modify Here to assign the value of mode from Environment Variable.
                                                
if (mode.equalsIgnoreCase("regression"))
{
try{
Runtime.getRuntime().exec("cmd /c tskill iexplore");                                                                    
logTestResult("All Active Browsers closed....", true,””);
}
catch(Exception e){
System.out.println("No Active Browsers present to close");
logTestResult ("No Active Browsers present to close", true,"");
}
sleep(5);
}             
                                               
if(appURL.equals("")){
logError("Application URL is blank");
logTestResult ("Application URL is blank", false,””);
return false;
}
//Start the application in browser with the obtained URL
startBrowser(appURL);
sleep(sleep_min);
//Returns true on success
return true;
}
catch (Exception e) {
logError("Unable to launch: " + appURL);
logTestResult ("Unable to launch: " + appURL, false,””);
return false;
}
}

Please feel free to reach me in case of queries and suggestions.

Tuesday, 2 December 2014

IBM Rational Functional Tester (RFT) - Descriptive Programming : Code to perform a key press action on already selected object on application.

IBM Rational Functional Tester (RFT) - Descriptive Programming : Code to perform a key press action on already selected object on application.


public boolean key_Press_withoutobject(String KeyName){
try{
boolean result = true;
getScreen().getActiveWindow().inputKeys(KeyName);
setLogMsg("Pressed Key: "+KeyName,true);

return result;
}
catch(ObjectNotFoundException e){
logTestResult("Object not found :" +e.getMessage()+" in keyword key_Press_withoutobject",false,"");
return false;
}
catch(NullPointerException e){
logTestResult("Null error :" +e.getMessage()+" in keyword key_Press_withoutobject",false,"");
return false;
}
catch(Exception e) {
logTestResult("Exception :" +e.getMessage()+" in keyword key_Press_withoutobject",false,"");
e.printStackTrace();
return false;
}
}

IBM Rational Functional Tester (RFT) - Descriptive Programming : Code to refresh a web page.

IBM Rational Functional Tester - Descriptive Programming Code to refresh a web page.

public void RefreshPage(){
try{
RootTestObject t = getRootTestObject();
TestObject[] Objects = t.find(SubitemFactory.atDescendant(
".class","Html.HtmlBrowser.ToolbarButton",".name","Reload"));
GuiTestObject btnReload = new GuiTestObject(Objects[0]);
btnReload.click();
}catch(Exception e){
logTestResult("Exception :" +e.getMessage()+" in keyword Page Refresh",false);
}
}
}