Access ALM Octane REST API using Python
Before you start working with the ALM Octane REST API, get a basic understanding of available resources and model reference — please checkout: ALM Octane Online Help & ALM Octane REST API Relations
Pre-requisites — Set Up Access
- Installation of Pyhton IDE, in this article PyCharm (Community Edition) is used.
- Download and Install Python, in this article Python 3.8. is used.
- Generate Client Id and Client Secret for ALM Octane: https://admhelp.microfocus.com/octane/en/latest/Online/Content/AdminGuide/how_setup_APIaccess.htm
Getting started!
Once you meet all the pre-requisites, follow the general integration flow of the ALM Octane REST API.
Import Required Modules
In your preferred IDE, create a new python script and import the following libraries/modules:
import json
import requests
import json — allows you to work with JavaScript Object Notation format
import requests — allows you to work with REST API requests and responses. It makes it easier to add content like headers, form data, multipart files, and parameters via simple Python libraries, as well as access the response data of Python in the same way.
Authenticate to ALM Octane REST API
ALM Octane REST API supports 3 sign-in methods:
- JSON authentication with user credentials or API access keys
- Basic authentication
- Interactive tools authentication
For more information, checkout the following link: https://admhelp.microfocus.com/octane/en/latest/Online/Content/API/Authenticate.htm#mt-item-0
In this article, JSON authentication with API access keys is used.
Define connection variables
url='https://<server>:<port>'
shared_space='155002'
workspace='1001'
client_id="IC_Api_wxx06129vggngbxdzxg0xm25d"
client_secret="-2xbx173x3354x890Q"
HeaderInfo={'Content-Type': 'application/json','ALM_OCTANE_TECH_PREVIEW': 'true'}
When connecting to ALM Octane REST API, following parameters need to be defined:
url: The ALM Octane Server URL
shared_space: The ID of the ALM Octane shared space
workspace: The ID of the ALM Octane workspace
client_id and client_secret: The API access key for the authentication to ALM Octane REST API.
HeaderInfo: Additional header information for the REST API requests. The ALM_OCTANE_TECH_PREVIEW flag need to be set to true to access the technical preview resources. Users should be aware that they are subject to change until declared public.
Sign-In to ALM Octane using the sign-in resource
URI: http[s]://<server>:<port>/authentication/sign_in
Supported HTTP method: POST
{
"client_id": "<client_id>",
"client_secret": "<client_secret>"
}
This resource sets the authentication cookies required for future requests.
Example Pyhton Code:
resource = 'authentication/sign_in'
payload={"client_id": client_id, "client_secret": client_secret}
resp = requests.post(url+'/' + resource,
data=json.dumps(payload),
headers=HeaderInfo)
cookie = resp.cookies
print('Login was successful with the status code: ' + str(resp.status_code))
Using the ‚authentication/sign_in’ resource the sign-in can be performed. The response contains the cookie, which need to be saved into a variable for future requests. Once the sign-in is successfully performed, it returns the status_code 200 in the response.
Example Output:
Login was successful with the status code: 200
Perform desired Actions
Is the sign-in performed, all resources are available listed here.
In the following, find some examples to read & create entities using ALM Octane REST API and Python.
Example 1: Get all Defects
URI: http[s]://<server>:<port>/api/shared_spaces/<space_id/workspaces/<workspace_id>/defects
Supported HTTP method: GET, POST, PUT, DELETE
For querying all defects, the GET method is used.
Example JSON response (displaying 2 defects):
{
"total_count": 274,
"data": [
{
"type": "defect",
"defect_root_level": null,
"release": null,
"sprint": null,
"defect_type": null,
"user_tags": {
"total_count": 0,
"data": []
},
"taxonomies": {
"total_count": 0,
"data": []
},
"detected_in_release": null,
"detected_by": null,
"qa_owner": null,
"owner": null,
"team": null,
"milestone": null,
"estimated_hours": 0,
"blocked": false,
"detected_in_build": null,
"closed_on": null,
"creation_time": "2018-10-31T06:50:18Z",
"remaining_hours": 0,
"name": "[MC] production coverage widget: when interval between from and to is too small",
"version_stamp": 14,
"story_points": null,
"id": "7292",
"blocked_reason": null,
"invested_hours": 0,
"fixed_in_build": null,
"description": null,
"last_modified": "2019-11-11T07:37:52Z",
"phase": {
"type": "phase",
"id": "phase.defect.fixed"
},
"severity": {
"type": "list_node",
"id": "list_node.severity.high"
},
"parent": {
"type": "work_item_root",
"id": "6001"
},
"author": {
"type": "workspace_user",
"id": "1004"
},
"product_areas": {
"total_count": 1,
"data": [
{
"type": "product_area",
"id": "6013"
}
]
},
"program": {
"type": "program",
"id": "3001"
},
"priority": {
"type": "list_node",
"id": "list_node.priority.very_high"
}
},
{
"type": "defect",
"defect_root_level": null,
"release": null,
"sprint": null,
"defect_type": null,
"user_tags": {
"total_count": 0,
"data": []
},
"taxonomies": {
"total_count": 0,
"data": []
},
"detected_in_release": null,
"detected_by": null,
"qa_owner": null,
"owner": null,
"team": null,
"milestone": null,
"estimated_hours": 0,
"blocked": false,
"detected_in_build": null,
"closed_on": null,
"creation_time": "2018-10-31T06:49:37Z",
"remaining_hours": 0,
"name": "[Regression Day] [Dashboard] [IE] Label in Mastercard graph is seen on top of drill down dialog",
"version_stamp": 9,
"story_points": null,
"id": "7267",
"blocked_reason": null,
"invested_hours": 0,
"fixed_in_build": null,
"description": null,
"last_modified": "2019-07-25T11:12:05Z",
"phase": {
"type": "phase",
"id": "phase.defect.fixed"
},
"severity": {
"type": "list_node",
"id": "list_node.severity.medium"
},
"parent": {
"type": "work_item_root",
"id": "6001"
},
"author": {
"type": "workspace_user",
"id": "1004"
},
"product_areas": {
"total_count": 1,
"data": [
{
"type": "product_area",
"id": "7006"
}
]
},
"program": {
"type": "program",
"id": "3001"
},
"priority": {
"type": "list_node",
"id": "list_node.priority.very_high"
}
},
}, {...} ]}
Example Pyhton Code:
The defect resource GET method is accessed with the HeaderInfo and cookie to extract all available defects from the workspace. The status_code returns 200, if the request was successfully performed. The defect JSON list in the response is loaded into the variable defects_data, which allows to extracts the total_count of all defect entries in defects_data. The ‚data’ array within the JSON response, contains the list of all defects. This list is saved into the defect_list variable. With ‚print(‚Total Defects: ‚ + str(total_count))’ the total count is printed in the python console. The for loop iterates through each row of the defect_list and prints the name, id and phase id of each line item (defect).
#Read all defects
resource='defects'
defects = requests.get(url+'/api/shared_spaces/' + shared_space + '/workspaces/'+ workspace +'/'+resource,
headers=HeaderInfo,
cookies=cookie)
print('Getting Defects Status: ' + str(defects.status_code))
defects_data = defects.json()
total_count = defects_data['total_count']
defect_list = defects_data['data']
print('Total Defects: ' + str(total_count))
#iterate through all defects
for defect in defect_list:
print('Defect Summary: ' + defect['name'] + ', ID: ' + defect['id'] + ', Phase: ' + defect['phase']['id'])
Example Output (displaying 3 defects):
Getting Defects Status: 200
Total Defects: 273
Defect Summary: [MC] production coverage widget: when interval between from and to is too small, ID: 7292, Phase: phase.defect.fixed
Defect Summary: [Regression Day] [Dashboard] [IE] Label in Mastercard graph is seen on top of drill down dialog, ID: 7267, Phase: phase.defect.fixed
Defect Summary: Activation E-mail sent to Yahoo e-mail address marked as spam, ID: 6077, Phase: phase.defect.new
… […]
Example 2: Get all Testcases
URI: http[s]://<server>:<port>/api/shared_spaces/<space_id/workspaces/<workspace_id>/tests
Supported HTTP method: GET, POST, PUT, DELETE
For querying all tests, the GET method is used.
Example JSON response (displaying 2 defects):
{
"total_count": 314,
"data": [
{
"type": "test",
"user_tags": {
"total_count": 0,
"data": []
},
"owner": null,
"test_type": {
"total_count": 0,
"data": []
},
"test_data_table": null,
"last_modified": "2019-10-07T07:49:08Z",
"creation_time": "2019-10-07T07:49:08Z",
"subtype": "test_manual",
"estimated_duration": null,
"description": null,
"steps_num": 0,
"name": "#Raute Test",
"version_stamp": 1,
"id": "41008",
"phase": {
"type": "phase",
"id": "phase.test_manual.new"
},
"author": {
"type": "workspace_user",
"id": "15001"
},
"product_areas": {
"total_count": 1,
"data": [
{
"type": "product_area",
"id": "24014"
}
]
},
"automation_status": {
"type": "list_node",
"id": "list_node.automation_status.not_automated"
},
"designer": {
"type": "workspace_user",
"id": "15001"
}
},
{
"type": "test",
"user_tags": {
"total_count": 0,
"data": []
},
"owner": null,
"test_data_table": null,
"last_modified": "2019-02-14T07:57:58Z",
"creation_time": "2018-12-06T12:27:31Z",
"subtype": "test_manual",
"estimated_duration": null,
"description": null,
"steps_num": 3,
"name": "Acceptance test",
"version_stamp": 4,
"id": "14001",
"phase": {
"type": "phase",
"id": "phase.test_manual.new"
},
"author": {
"type": "workspace_user",
"id": "13001"
},
"product_areas": {
"total_count": 2,
"data": [
{
"type": "product_area",
"id": "7004"
},
{
"type": "product_area",
"id": "8001"
}
]
},
"automation_status": {
"type": "list_node",
"id": "list_node.automation_status.not_automated"
},
"designer": {
"type": "workspace_user",
"id": "13001"
},
"test_type": {
"total_count": 1,
"data": [
{
"type": "list_node",
"id": "list_node.test_type.acceptance"
}
]
}
}, {...} ]}
Example Pyhton Code:
The tests resource GET method is accessed with the HeaderInfo and cookie to extract all available tests from the workspace. The status_code returns 200, if the request was successfully performed. The test JSON list in the response is loaded into the variable tests_data, which allows to extracts the tests_total_count of all test entries in tests_data. The ‚data’ array within the JSON response, contains the list of all tests. This list is saved into the tests_list variable. With ‚print(‚Total Tests: ‚ + str(tests_total_count))’ the total count is printed in the python console. The for loop iterates through each row of the tests_list and prints the name, id and subtype of each line item (test).
#Read all tests
resource='tests'
tests = requests.get(url + '/api/shared_spaces/' + shared_space + '/workspaces/'+ workspace +'/' +resource,
headers=ContentType,
cookies=cookie)
print('Getting Tests Status: ' + str(tests.status_code))
tests_data = tests.json()
tests_total_count = tests_data['total_count']
tests_list = tests_data['data']
print('Total Tests: ' + str(tests_total_count))
#iterate through all Programs
for test in tests_list:
print('Test Name: ' + test['name'] + ', ID: ' + test['id'] + ', Type: ' + test['subtype'])
Example Output (displaying 4 tests):
Getting Tests Status: 200
Total Tests: 314
Test Name: #Raute Test, ID: 41008, Type: test_manual
Test Name: Acceptance test, ID: 14001, Type: test_manual
Test Name: Account Creation, ID: 7010, Type: test_automated
Test Name: Account Management, ID: 32001, Type: test_suite
… […]
Example 3: Get all Programs
The program resource is a technical preview resource, which is not listed in the public resources of the ALM Octane REST API. To access this resource, make sure the flag ALM_OCTANE_TECH_PREVIEW is set to true.
URI: http[s]://<server>:<port>/api/shared_spaces/<space_id/workspaces/<workspace_id>/programs
Supported HTTP method: GET, POST, PUT, DELETE
For querying all programs, the GET method is used.
Example JSON response (displaying 3 programs):
{
"total_count": 3,
"data": [
{
"type": "program",
"last_modified": "2019-03-19T16:59:35Z",
"name": "Mobile Service",
"id": "2002",
"version_stamp": 1,
"creation_time": "2019-03-19T16:59:35Z"
},
{
"type": "program",
"last_modified": "2019-04-11T16:08:41Z",
"name": "Service Center CRM",
"id": "3001",
"version_stamp": 1,
"creation_time": "2019-04-11T16:08:41Z"
},
{
"type": "program",
"last_modified": "2019-06-07T08:38:30Z",
"name": "SOA Integrity",
"id": "5001",
"version_stamp": 1,
"creation_time": "2019-06-07T08:38:30Z"
}
],
"exceeds_total_count": false}
Example Python Code:
The program resource GET method is accessed with the HeaderInfo and cookie to extract all available tests from the workspace. Important is to add the ALM_OCTANE_TECH_PREVIEW flag set to true in the HeaderInfo. The status_code returns 200, if the request was successfully performed. The program JSON list in the response is loaded into the variable programs_data, which allows to extracts the programs_total_count of all program entries in programs_data. The ‚data’ array within the JSON response, contains the list of all programs. This list is saved into the programs_list variable. With ‚print(‚Total Programs: ‚ + str(programs_total_count))’ the total count is printed in the python console. The for loop iterates through each row of the programs_list and prints the name, id and type of each line item (program).
#Read Programs
resource='programs'
programs = requests.get(url + '/api/shared_spaces/' + shared_space + '/workspaces/'+ workspace +'/' +resource,
headers=ContentType,
cookies=cookie)
print('Getting Program Status: ' + str(programs.status_code))
programs_data = programs.json()
programs_total_count = programs_data['total_count']
programs_list = programs_data['data']
print('Total Programs: ' + str(programs_total_count))
#iterate through all Programs
for program in programs_list:
print('Program Name: ' + program['name'] + ', ID: ' + program['id'] + ', Type: ' + program['type'])
Example Output (displaying 3 programs):
Getting Program Status: 200
Total Programs: 3
Program Name: Mobile Service, ID: 2002, Type: program
Program Name: Service Center CRM, ID: 3001, Type: program
Program Name: SOA Integrity, ID: 5001, Type: program
… […]
Example 4: Creating a Defect
URI: http[s]://<server>:<port>/api/shared_spaces/<space_id/workspaces/<workspace_id>/defects
Supported HTTP method: GET, POST, PUT, DELETE
For creating a new defect, the POST method is used.
Example Payload (min. required fields):
{
"data":
[
{"name":"REST API Defect",
"description":"This is a test defect created from REST API",
"phase":
{"id":"phase.defect.new",
"type":"phase"}
}
]
}
Example Python Code:
For creating a new entity using the REST API of ALM Octane, the POST method need to be used. Additionally, the payload for the data need to be passed in the POST request. In the following example a new defect is created with a payload defined in the defect_data variable. Once the request is successfully performed, ALM Octane returns 201 as status_code and the ID of the total created entities. In this case, the id of the created defect is returned.
resource='defects'
defect_data = {"data":[{"name":"REST API Defect", "description":"This is a test defect created from REST API", "phase":{"id":"phase.defect.new", "type":"phase"}}]}
defects = requests.post(url+'/api/shared_spaces/' + shared_space + '/workspaces/'+ workspace +'/'+resource,
data=json.dumps(defect_data),
headers=ContentType,
cookies=cookie)
print('Creating Defect Status: ' + str(defects.status_code))
print('Defect with ID: ' + defects.json()['data'][0]['id'] + ' created successfully.')
Example Output:
Creating Defect Status: 201
Defect with ID: 54007 created successfully.
Screenshot in ALM Octane of the created Defect:
Disconnect
When all desired actions are performed, disconnect from the ALM Octane REST API using the cookie which was returned by the ALM Octane server after authentication.
URI: http[s]://<server>:<port>/authentication/sign_out
Supported HTTP method: POST
Example Python Code:
When accessing the sign-out resource, the POST method is used. It requires the same cookie which was initially generated by the ALM Octane server, when the sign-in was performed.
#Logout from Octane
resource='authentication/sign_out'
resp = requests.post(url+'/' + resource,
data=json.dumps(payload),
headers=ContentType,
cookies=cookie)
print('Logout was successful with the status code: ' + str(resp.status_code))
Example Output:
Logout was successful with the status code: 200
Conclusion
For all users who enjoyed the simplicity of Visual Basic using ALM/QC API (OTA Library), Python is a great option. Python offers json and requests modules to allow easy interaction with the ALM Octane REST API.
Start your ALM Octane Trial: https://www.microfocus.com/en-us/products/alm-octane/free-trial
#DevOps #Enterprise #Modern #Quality #Management #Insight #Agile #Scrum #AnInfographicADayKeepsTheCompetitionAway