Access ALM Octane REST API using Python

ALM Octane
9 min readNov 13, 2019

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

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

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

ALM Octane
ALM Octane

Written by ALM Octane

ALM Octane is a DevOps Lifecycle Management software for organizations to scale agile development from team level to the enterprise. https://embrace-devops.com

No responses yet

Write a response