Technical Articles
Integrate Jenkins Automation Server in an eCATT Test Process
At the moment moves the focus in our development more to native apps of mobile devices. In this context it is my goal to integrate the test envinronment of this app development in our eCATT scripts. The colleguaes of app develpment uses Jenkins, a fantastic automation server which supports developers in continuous integration (CI). The developers don’t do their builds with Jenkins only, the do also developer tests. And from this perspective we expect a synergy effect between the development tests outside SAP and test automation inside SAP.
In this scenario we use PowerShell as the bridge between Jenkins and the SAP backend. I described the way here, and an extension here.
Here my steps to integrate Jenkins inside eCATT script at SAP backend:
At first I installed Jenkins. An easy task, I used the web archive (war), open Jenkins in my browser with http://localhost:8080 and installed the plugins.
In the next step I installed an additional plugin to execute PowerShell scripts in Jenkins build processes.
Now I developed a tiny example remote enabled function module (RFM) at the SAP backend to receive a status and to store it in a table.
FUNCTION YRFCTEST.
*"----------------------------------------------------------------------
*"*"Lokale Schnittstelle:
*" IMPORTING
*" VALUE(IV_RESULT) TYPE BOOLEAN
*"----------------------------------------------------------------------
DATA:
ls_rfcresult TYPE YRFCRESULT
.
LS_RFCRESULT-TIMESTAMP = SY-DATUM && SY-UZEIT.
LS_RFCRESULT-BUILD_RESULT = IV_RESULT.
INSERT YRFCRESULT FROM ls_rfcresult.
ENDFUNCTION.
In the next step I developed a PowerShell script to set the status. This script uses dotNET connector (NCo) to connect the SAP system – you can find more information here.
#-Begin-----------------------------------------------------------------
#-Sub Load-NCo--------------------------------------------------------
Function Load-NCo {
[String]$ScriptDir = "C:\NCo"
If ([Environment]::Is64BitProcess) {
[String]$Path = $ScriptDir + "\x64\"
} Else {
[String]$Path = $ScriptDir + "\x86\"
}
[String]$File = $Path + "sapnco.dll"; Add-Type -Path $File
$File = $Path + "sapnco_utils.dll"; Add-Type -Path $File
}
#-Function Get-Destination--------------------------------------------
Function Get-Destination {
#-Verbindungsparamter-----------------------------------------------
$cfgParams = `
New-Object SAP.Middleware.Connector.RfcConfigParameters
$cfgParams.Add($cfgParams::Name, "TEST")
$cfgParams.Add($cfgParams::AppServerHost, "localhost")
$cfgParams.Add($cfgParams::SystemNumber, "00")
$cfgParams.Add($cfgParams::Client, "000")
$cfgParams.Add($cfgParams::User, "BCUSER")
$cfgParams.Add($cfgParams::Password, "minisap")
Return [SAP.Middleware.Connector.RfcDestinationManager]::GetDestination($cfgParams)
}
#-Sub Invoke-SAPFunctionModule----------------------------------------
Function Invoke-SAPFunctionModule {
$destination = Get-Destination
#-Metadaten---------------------------------------------------------
$rfcFunction = `
$destination.Repository.CreateFunction("YRFCTEST")
#-Importparameter setzen--------------------------------------------
$rfcFunction.SetValue("IV_RESULT", "X")
#-Funktionsbaustein aufrufen----------------------------------------
$rfcFunction.Invoke($destination)
}
#-Sub Main------------------------------------------------------------
Function Main () {
Load-NCo
Invoke-SAPFunctionModule
}
#-Main----------------------------------------------------------------
Main
#-Error routine-------------------------------------------------------
Trap {
[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") > $Null
[Void] [System.Windows.Forms.MessageBox]::Show( `
$_.Exception.GetType().FullName + `
[System.Environment]::NewLine + `
"Error at line " + $_.InvocationInfo.ScriptLineNumber + `
" in " + $_.InvocationInfo.ScriptName + `
[System.Environment]::NewLine + [System.Environment]::NewLine + `
$_.Exception.Message, "An Error Occurred", 0)
Exit
}
#-End-------------------------------------------------------------------
I integrated this script into my build process in Jenkins.
And after I start the build process in Jenkins, I got my entry in the table in the SAP system.
So far so well, on this way it is possible to send the result of a build process from Jenkins to an SAP system.
Last but not least a PowerShell script to execute the build process via Jenkins remote API.
#-Begin-----------------------------------------------------------------
#-Sub Main--------------------------------------------------------------
Function Main() {
$URI = "http://localhost:8090";
$User = "BCUSER";
$Password = "minisap";
$Headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]";
$Bytes = [System.Text.Encoding]::UTF8.GetBytes("$($User):$Password");
$Base64 = [System.Convert]::ToBase64String($Bytes);
$Headers.Add("Authorization","Basic $Base64");
[xml]$Crumbs = Invoke-WebRequest "$URI/crumbIssuer/api/xml" `
-Method Get -Headers $Headers;
$Headers.Add($Crumbs.defaultCrumbIssuer.crumbRequestField, `
$Crumbs.defaultCrumbIssuer.crumb);
$Headers.Add("Accept", "application/xml");
$Result = Invoke-WebRequest -Uri "$URI/job/Test/build" `
-Method Post -Headers $Headers;
}
#-Main------------------------------------------------------------------
Main
#-Error Routine---------------------------------------------------------
Trap {
[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") > $Null
[Void] [System.Windows.Forms.MessageBox]::Show( `
$_.Exception.GetType().FullName + `
[System.Environment]::NewLine + `
"Error at line " + $_.InvocationInfo.ScriptLineNumber + `
" in " + $_.InvocationInfo.ScriptName + `
[System.Environment]::NewLine + [System.Environment]::NewLine + `
$_.Exception.Message, "An Error Occurred", 0)
Exit
}
#-End-------------------------------------------------------------------
And to close the circle you can call this PowerShell script from your eCATT script.
It is possible to execute Jenkins build processes from eCATT. Also you can get a result from the asynchronous build process for further operations of the eCATT test script.
It will be seen if this approach will work in practice. However, the prospect of this kind of integration itself is great.
Hello Stefan, very interesting. Thanks for sharing.
Is there a benefit of using a Powershell script over an Abap API to trigger a Jenkins Build via a webhook in your scenario?
Kind regards,
Alex
Hello Alexander,
thanks for your reply.
Not really. It is one way and if you use Windows OS on your frontend server it is available and offers many possibilities without any additional installation. But certainly you can choose also other approaches to integrate Jenkins in eCATT.
Best regards
Stefan