Seamless integration of test automation into the CI/CD pipeline is essential in today's DevOps landscape. SAP Enterprise Continuous Testing by Tricentis, especially the recently released full SaaS version, enables automated tests to be executed at scale with minimal effort. This post will teach you how to integrateĀ SAP Enterprise Continuous Testing by Tricentis with Jenkins, run tests automatically, and retrieve results directly within the build process.
Prerequisites:
To follow this guide, youāll need:
- š„Ā A Jenkins server (local or remote) with admin privileges
- ā Ā A configured Playlist in SAP Enterprise Continuous Testing by Tricentis
- š¤Ā An active Team-Agent in SAP Enterprise Continuous Testing by Tricentis
- šĀ Admin access in SAP Enterprise Continuous Testing by Tricentis to obtain API credentials
- šŖŖ A validĀ SAP Enterprise Continuous Testing by Tricentis API access token
Step-by-step instructions
š”Ā Set UpĀ SAP Enterprise Continuous Testing by Tricentis API Access
- Open the Swagger documentation of your tenant: https://<your_tenant>.my-sap.tricentis.com/_identity/apiDocs/swagger/index.html
- Authenticate via the "Authorize" button.
- Execute GET /_identity/api/v1/applications and locate the entry Tricentis_Cloud_API.
- Copy the corresponding ID.
- Use that ID to execute GET /_identity/api/v1/applications/{id}/secrets to retrieve your clientSecret.
š ļø Configure Jenkins Pipeline
In Jenkins, create a new Pipeline job and define the following environment block:
environment {
CLIENT_ID = 'Tricentis_Cloud_API' //Client ID from the identity service: https://documentation.tricentis.com/sap/ect_cloud/en/content/references/tosca_apis.htm
CLIENT_SECRET = '<CLIENT_SECRET>'
E2G_SCOPE = 'tta'
E2G_AUTH_URL = '<Token_URL>' //https://documentation.tricentis.com/sap/ect_cloud/en/content/admin_guide/get_client_secret.htm
TTA_URL = '<URL of your Tenant>' //Your ECT Cloud tenant URL including the workspace name
PLAYLIST_ID = 'Playlist ID from your playlist URL'
}- E2G_AUTH_URL, can be copied from Swagger after authorization:
- Select āAuthorizeā
- CopyĀ Token URL
- TTA_URLĀ depends on your workspace. In our example, we used āDefaultā.Ā Ā
- PLAYLIST_ID,Ā can be found in SAP Enterprise Continuous Testing by Tricentis under Playlists (copy from the URL)
- https://<your_tenant>.my-sap.tricentis.com/_portal/space/Default/playlists/edit/<playlistID>
- You can also parameterize values such as PLAYLIST_ID for more flexibility.
In the script section, you have to add the name of the parameter.
environment {
CLIENT_ID = 'Tricentis_Cloud_API' //Client ID from the identity service: https://documentation.tricentis.com/sap/ect_cloud/en/content/references/tosca_apis.htm
CLIENT_SECRET = '<CLIENT_SECRET>'
E2G_SCOPE = 'tta'
E2G_AUTH_URL = '<Token_URL>' //https://documentation.tricentis.com/sap/ect_cloud/en/content/admin_guide/get_client_secret.htm
TTA_URL = '<URL of your Tenant>' //Your ECT Cloud tenant URL including the workspace name
PLAYLIST_ID = "${PlaylistId}"
}šĀ Script āĀ Get Token
This stage makes a secure request to get your OAuth2 access token.
- Request type:Ā application/x-www-form-urlencoded
- Parameters:Ā client_id,Ā client_secret,Ā scope,Ā grant_type
- If successful, theĀ access_tokenĀ is saved to a file (e.g., access_token.txt)
- If not, the pipeline exits with an error
stage('Get Token') {
powershell '''
$headers = @{
"Content-Type" = "application/x-www-form-urlencoded"
}
#Getting the access token as pre-authentication based on the manual: https://documentation.tricentis.com/sap/ect_cloud/en/content/admin_guide/get_client_secret.htm
$Body = "client_id=$env:CLIENT_ID&client_secret=$env:CLIENT_SECRET&scope=$env:E2G_SCOPE&grant_type=client_credentials"
$maxRetries = 3
$retryCount = 0
$success = $false
do {
try {
$response = Invoke-RestMethod -Uri "$env:E2G_AUTH_URL" -Method "Post" -Headers $headers -Body $Body
#Save access token from response
$accessToken = $response.access_token
$success = $true
Write-Host "Token acquired successfully."
}
catch {
$retryCount++
Write-Host "Token acquisition failed (attempt $retryCount of $maxRetries): $($_.Exception.Message)"
if ($retryCount -lt $maxRetries) {
Start-Sleep -Seconds 5
}
}
} while (-not $success -and $retryCount -lt $maxRetries)
if (-not $success) {
throw "Failed to acquire token after $maxRetries attempts"
}
# Save token to file for use in subsequent stages
$accessToken | Out-File -FilePath "access_token.txt" -Encoding UTF8
'''
}šĀ Script āĀ Run Tests
Using the token:
- Read the token fromĀ access_token.txt
- Send aĀ POST request to /api/v2/playlistRuns/ with the playlist ID
- Save the returnedĀ executionIdĀ toĀ execution_id.txtĀ ā youāll need it to track progress
stage('Run Tests') {
powershell '''
#Read access token from temporary file
$accessToken = Get-Content -Path "access_token.txt" -Raw
$accessToken = $accessToken.Trim()
function StartPlaylistExecution {
param(
[string]$AccessToken,
[string]$TtaUrl,
[string]$PlaylistId
)
try {
$headers = @{
"Authorization" = "Bearer $AccessToken"
"Content-Type" = "application/json"
"Accept" = "application/json"
}
$body = @{
"playlistId" = $PlaylistId
"private" = $false
} | ConvertTo-Json
$fullUrl = "$TtaURL/_playlists/api/v2/playlistRuns/"
Write-Host "Calling: $fullUrl"
#Sending playlist run of specific playlist based on the Playlist ID provided
$response = Invoke-RestMethod -Uri $fullUrl -Method Post -Headers $headers -Body $body
if ($response.executionId) {
return $response.executionId
} elseif ($response.id) {
return $response.id
} else {
throw "No execution ID returned."
}
}
catch {
Write-Error "Execution failed: $($_.Exception.Message)"
throw
}
}
$executionId = StartPlaylistExecution $accessToken $env:TTA_URL $env:PLAYLIST_ID
Write-Host "Execution triggered. ID: $executionId"
# Save execution ID to file for use in subsequent stages
$executionId | Out-File -FilePath "execution_id.txt" -Encoding UTF8
'''
}ā±Ā Script āĀ Wait for Results
Your pipeline now polls SAP Enterprise Continuous Testing by Tricentis every 30 seconds to check test status:
- Possible states:Ā running,Ā succeeded,Ā failed,Ā canceled
- Once completed, the status is saved toĀ test_state.txt
- On failure: pipeline exits immediately with an error code
stage('Wait for Results') {
powershell '''
# Read token and execution ID from files
$accessToken = Get-Content -Path "access_token.txt" -Raw
$accessToken = $accessToken.Trim()
$executionId = Get-Content -Path "execution_id.txt" -Raw
$executionId = $executionId.Trim()
function WaitForExecution {
param(
[Parameter(Mandatory=$true)]
[string]$AccessToken,
[Parameter(Mandatory=$true)]
[string]$TtaUrl,
[Parameter(Mandatory=$true)]
[string]$ExecutionId,
[Parameter(Mandatory=$false)]
[int]$TimeoutMinutes = 60,
[Parameter(Mandatory=$false)]
[int]$PollingIntervalSeconds = 30
)
try {
$headers = @{
"Authorization" = "Bearer $AccessToken"
"Content-Type" = "application/json"
}
$startTime = Get-Date
$timeoutTime = $startTime.AddMinutes($TimeoutMinutes)
Write-Host "Waiting for execution with Playlist ID $ExecutionId to complete..."
do {
$response = Invoke-RestMethod -Uri "$TtaUrl/_playlists/api/v2/playlistRuns/$ExecutionId" -Method Get -Headers $headers
$status = $response.state
$playListName = $response.playlistName
Write-Host "Current execution status: $status"
if ($status -eq "Completed" -or $status -eq "succeeded") {
return "succeeded"
}
if ($status -eq "Failed" -or $status -eq "failed") {
return "failed"
}
if ($status -eq "Cancelled" -or $status -eq "canceled" -or $status -eq "canceling") {
return "canceled"
}
if ((Get-Date) -gt $timeoutTime) {
Write-Host "Execution timed out after $TimeoutMinutes minutes"
return $null
}
#Wait x amount of seconds and check again if Playlist run has finished
Write-Host "Execution of Playlist $playListName still running. Waiting $PollingIntervalSeconds seconds before next check..."
Start-Sleep -Seconds $PollingIntervalSeconds
} while ($status -eq "Running" -or $status -eq "Pending" -or $status -eq "Starting")
return $status
}
catch {
Write-Error "Failed to wait for execution: $($_.Exception.Message)"
throw
}
}
$currentState = WaitForExecution $accessToken $env:TTA_URL $executionId
if ($currentState -eq $null) {
throw "Execution timed out"
}
if ($currentState -eq 'canceling' -or $currentState -eq 'canceled') {
throw "Execution Canceled"
}
# Stops pipeline if playlist execution has status failed. Remove if you want to release with a failed playlist run.
if ($currentState -eq 'failing' -or $currentState -eq 'failed') {
throw "Execution Failed"
}
Write-Host "Test execution completed with state: $currentState"
# Save test state to file for use in subsequent stages
$currentState | Out-File -FilePath "test_state.txt" -Encoding UTF8
'''
}šĀ Script āĀ Get JUnit Results
Once the run is finished:
- Call theĀ SAP Enterprise Continuous Testing by Tricentis - Cloud API to retrieve the JUnit report
- Save it locally asĀ junit-results.xml
- Analysis: The XML is parsed, e.g., to read out the number of tests, errors, or runtimes.
stage('Get JUnit Results') {
powershell '''
# Read token and execution ID from files
$accessToken = Get-Content -Path "access_token.txt" -Raw
$accessToken = $accessToken.Trim()
$executionId = Get-Content -Path "execution_id.txt" -Raw
$executionId = $executionId.Trim()
function GetJUnitResults {
param(
[Parameter(Mandatory=$true)][string]$AccessToken,
[Parameter(Mandatory=$true)][string]$TtaUrl,
[Parameter(Mandatory=$true)][string]$ExecutionId
)
try {
$headers = @{
"Authorization" = "Bearer $AccessToken"
"Accept" = "application/xml"
}
$fullUrl = "$env:TTA_URL/_playlists/api/v2/playlistRuns/$ExecutionId/junit"
$response = Invoke-RestMethod -Uri $fullUrl -Method Get -Headers $headers
# Save JUnit XML to file
$junitXml = $response.OuterXml
$junitXml | Out-File -FilePath "junit-results.xml" -Encoding UTF8
# Parse and display summary
$xmlDoc = [xml]$junitXml
$testsuites = $xmlDoc.testsuites
return $junitXml
}
catch {
Write-Error "Failed to get JUnit results: $($_.Exception.Message)"
throw
}
}
$junitResults = GetJUnitResults $accessToken $env:TTA_URL $executionId
Write-Host "JUnit results retrieved successfully"
'''
}ā Ā Script āĀ Check Final Status
- Reads the test status fromĀ test_state.txt.
- Stops the pipeline on error status (error, failed) with exit 1.Ā If required, you can modify this to allow non-blocking behavior if needed.
- Outputs a success message on positive completion.
stage('Check Final Status') {
powershell '''
# Read test state from file
$testState = Get-Content -Path "test_state.txt" -Raw
$testState = $testState.Trim()
if ($testState -eq 'error') {
Write-Host "##[error]Tests error!"
exit 1
} else {
Write-Host "Tests run finished successfully!"
}
'''
}šĀ Script -Ā Publish Test Results
- UploadsĀ junit-results.xml
- Displays test results in Jenkins
- Prevents failure of empty reports
stage('Publish Test Results') {
steps {
script {
// Publish JUnit test results
if (fileExists('junit-results.xml')) {
junit testResults: 'junit-results.xml', allowEmptyResults: true, keepLongStdio: true
echo "Test results published successfully"
} else {
echo "No test result files found to publish"
}
}
}Documentation & References
SAP Enterprise Continuous Testing by Tricentis - Cloud API:Ā https://documentation.tricentis.com/sap/ect_cloud/en/content/references/tosca_apis.htmĀ
Conclusion
Following this setup allows you to fully automate your SAP Enterprise Continuous Testing by Tricentis test cases via Jenkins, complete with token management, playlist triggering, status monitoring, and test result reporting. This integration enables you to maintain high-quality test automation directly within your CI/CD pipelines.