Saturday, October 19, 2013

Automating SAP portal based application automation issues and possible resolutions

Few challenges which I have encountered while automating the SAP portal based applications and I am trying to put them below hoping it would help someone like me (or probably me in future looking for help :-) about code) :

Before going to the specific challenges I would like to write about what I have understood about the SAP NetWeaver portal. They have tried to standardize the controls by clubbing basic HTML web elements in a specific order and then come up with a framework for the portal. So basically at the core it is web add in which helps to identify the objects on the application. Since the portal is relatively new (compared to ECC), it is not as stable as ECC is when it comes to automating the UI using QTP. In this context few of the challenges which I am trying to document below:

1. SAPCombo: It is recorded by the tool but when you try to play back the script the control is not identified by the tool. How it actually works is that when you spy the object you will find that it is a WebEdit and on its click event a webtable opens up which contains the elements of the combo box. To handle this there may be two ways:

a. First add the WebEdit to your object repository-> click on WebEdit in the code-> create a description of the web element from the table you want to click-> add web table to the repository-> use child item method of the WebTable to click on the element you want to click

objDesc=Description.create
objDesc("micClass").value="WebElement"
objDesc("name").value="One"

Browser("Browser").Page("Page").WebEdit("EditBox").click
set childobj=Browser("Browser").Page("Page").WebTable("Table").childobjects(objDesc)
childobj(0).click  (Just find out which native method this object support and invoke that method)

b. Create a Wscript.Shell object and use the sendkey method to perform the action. There may be issues while using this method and I prefer the above method, but in some case when you are not able to figure out the unique identification properties or the placement of the WebEdit(required for childitem method) object in the table cell, it is the method left to go with and works well.

2. SAPEdit: I have noticed that qtp tries to identify the SapEdit using html id property to identify the object, but every time you login a new id is assigned to the object and the script fails. I try to solve this problem is by going by regular expression and index property. Mostly the id is represented something like: WD78DA, where initial WD is constant and remaining string keeps changing. To address this issue what I do is put it as a regular expression- WD.*, and then find out the index of the edit box on the screen and use this property. I have not see this index changing and it helps me to solve this issue. Don't forget to remove the "sapattachedtext" property if that is being used by the tool

3. SAPEdit inside a WebTable: In such case apart from going by indexes and regular expression, you can use childitem method to enter the value in a particular SAPEdit box embedded inside the WebTable.

Browser().Page().WebTable().childItem(1,2, "WebEdit",0).set "Value"

4.SAPButton: Sometimes I have experienced that when you are adding and SAPButton using add button in the object repository, you will find two SAPButton objects at the bottom in the object hierarchy which QTP is showing, in that case you just go ahead and check the second last object in the hierarchy as I have experienced that it had the name property which helped tool to identify the object while execution whereas tool faced difficulty when I added the last object in the hierarchy as it did not have fixed recognition properties associated with the object.

Please post other issues as well if you have faced while automating SAP netweaver portal and how you resolved those. That would help. Thanks.

Tuesday, October 8, 2013

Some Custom functions in QTP

I am placing few of the custom function which I have written, below. These can be reused in the same form without changes and will try to add more here.

'***************************************************************************
Function current_date(date_format)
dim c_date
   Select Case date_format
  Case "dd.mm.yyyy"
c_date=Day(now())&"."&Month(Now())&"."&Year(Now())

Case "dd/mm/yyyy"
c_date=Day(now())&"/"&Month(Now())&"/"&Year(Now())
   End Select

   current_date=c_date
End Function

'***************************************************************************
Sub sap_exit()
SAPGuiSession("type:=GuiSession","name:=ses.0.").Reset " "
SAPGuiSession("type:=GuiSession","name:=ses.0.").Reset "ex"
End Sub

'***************************************************************************
'This function returns arrays of dates from_date to to_date
Function middle_dates(from_date, to_date)
f_date=getdate(from_date)
t_date=getdate(to_date)

'msgbox "start:"&f_date &"/n End:" & t_date
diff=datediff("d",f_date,t_date)
num_elements=CInt(diff)
dim arr_date()
ReDim arr_date(num_elements)
arr_date(0)=format_date(f_date,"dd.mm.yyyy")
For counter=1 to diff
d_var=dateadd("d", counter,f_date)
arr_date(counter)=format_date(d_var, "dd.mm.yyyy")
Next
middle_dates=arr_date
End Function
'***************************************************************************
' This function takes date in dd.mm.yyyy format and convert it to the system date format to be processed
function getdate(d)
str=Split(d,".")
str_day=str(0)
str_month=str(1)
str_year=str(2)
d=dateserial(str_year,str_month,str_day)
'msgbox d
getdate=d
end function
'***************************************************************************
'This cuntion converts date to the required format
Function format_date(dt, format)
return_date=""
  d=CInt(day(dt))
If d<10 Then
d="0"&cstr(d)
End If

m=cint(month(dt))
If m<10 Then
m="0" & cstr(m)
End If

y=year(dt)

Select Case (format)
Case "dd.mm.yyyy"
 return_date=d &"." & m & "." & y 

End Select
format_date=return_date
End Function
'***************************************************************************
'get temp file path
Function getTempFilePath(fileName)
Set objShell = CreateObject("WScript.Shell")
Set colEnvironment = objShell.Environment("PROCESS")
objPath = colEnvironment("temp")
getTempFilePath=objPath&"\"&fileName
End Function
'***************************************************************************
'Generic function to capture screenshot
'Funciton to capture the screenshot
Function CaptureScreenshot(obj)
obj.capturebitmap gettempfilepath("screenshot.png"), true
    CaptureScreenshot=gettempfilepath("screenshot.png")
End Function

'***************************************************************************
'Function Name:current_time
'Function returns current time in HH:MM:SS format
'******************************************************************************************************************
Function current_time()
   current_time=hour(now())&":"&minute(now())&":"&second(now())
End Function
'***************************************************************************
'This subroutine logs SAP status bar event
Sub ReportStatusBarEvent_Desc(obj,desc, screenshot)
   text=obj.getROProperty("text")
   msgtype=obj.getROProperty("messagetype")
If Strcomp(msgtype,"S",1)=0 Then
reporter.ReportEvent  micPass,desc, text, screenshot
else
reporter.ReportEvent  micFail,desc, text, screenshot
End If
End Sub


'******************************************************************************************************************
'Function Name:CustomWait
'Description:This function is written to have custom wait on object
'******************************************************************************************************************
Sub CustomWait(obj, MaxWaitTime)
flag=true
counter=0
While (flag AND counter<=MaxWaitTime)
If obj.exist Then
'If obj.getroproperty("enabled") Then
flag=false
wait 3
'End If
else
wait 3
counter=counter+3
End If
Wend
End Sub

'*****************************************************************************************************************
'Function Name:CustomSendKeys
'Description:Function to use sendkeys operation
'******************************************************************************************************************
Sub CustomSendKeys(obj, desc)
    set wsh=createobject("WScript.Shell")
wsh.SendKeys desc
Set wsh=nothing
End Sub
'******************************************************************************************************************

'You can register these functions with multiple object using registeruserfunc .