HP ALM REST API

Many companies use HP ALM (formerly known as Quality Center) for storing test cases and test results.  ALM’s companion test automation tool is another HP product called UFT (formerly know as QTP).  If you use another automation tool (for example… Selenium), it is not easy to save test results in ALM.  While it is not easy, it is possible to save external test results to ALM using an HP API.  HP has provided two API’s that can be used to do this:

A) OTA API

B) REST API

There are plenty of examples on the web if you want to use the OTA.  I would suggest against doing this since the REST API is newer and will be supported going forward.

In this article I am going to show you how to log external test results using a series of web service requests:

  1. Authentication
  2. Create a new session
  3. Using a testset ID to return a list of test ID’s
  4. Create a new testrun in testlab
  5. Update the new testrun in testlab
  6. Logout

You will need to build requests, submit them to the ALM server, and then extract crucial data from the response XML.  The examples in this article are code agnostic so it will be up to you to write and execute the requests.  When I did this in C# I wrote the HTTP requests by hand, but you might find it easier to use a REST client like RestSharp.  If you are scripting in another language, there are a plethora of REST clients available for Java, Javascript, Python, etc.

1) Authentication

To authenticate, update this XML with your credentials and submit as a POST request.

Request Type:  POST

Header:
ContentType = “application/xml”
Accept = “application/xml”

Cookie Container:  N/A

URI:

http://targetserver:targetport/qcbin/authentication-point/alm-authenticate

XML:

<alm-authentication>
 <user>ALMusername</user> 
 <password>ALMpassword</password> 
</alm-authentication>

You should get a successful response from the server.  If not, you need to double check your credentials and fix this request before attempting to proceed any further.

Make sure to extract the LWSSO_COOKIE_KEY value from the response XML and store that value inside a variable which will be used in subsequent requests.

2) Create a new session

Now that you are authenticated, you must create a new session before you can do anything else.  When you build this request, you must also create a cookie container and add the LWSSO_COOKIE_KEY value to the container.

Request Type:  POST

Cookie Container:

  • LWSSO_COOKIE_KEY

Header:
ContentType = “application/xml”
Accept = “application/xml”

URI:

http://targetserver:targetport/qcbin/rest/site-session

XML:  N/A

You must extract three values (QCSession, ALM_USER, XSRF-TOKEN) from the response XML and store these values inside variables which will be used in subsequent requests.

3) Using a testset ID to return a list of test ID’s

You need to get the config ID, test ID, and testset ID of the testset that you want to update in ALM testlab. The testset ID will be used to run a query to get a list of test instance ID’s.

In this example my testset is a manual test.  To get the testset ID, right-click on the testset and select “Test Set Details”

testset

Request Type:  GET

Header:
ContentType = “application/xml”
Accept = “application/xml”

Cookie Container:

  • LWSSO_COOKIE_KEY
  • QCSession
  • ALM_USER
  • XSRF-TOKEN

URI:

http://targetserver:targetport/qcbin/rest/domains/ALMDomain/projects/ALMProject/test-instances?query={cycle-id[#####]}

(##### is the testset ID)

XML:  N/A

This is the portion of the response XML that we are interested in:

<Field Name="id">
 <Value>#####</Value>
</Field>

This is the test instance ID.  You will want to create a list or array to hold all of these ID’s.

For the purpose of this article we will only be using the first test instance ID found inside the XML response.

4) Create a new testrun in testlab

What we want to do next is create a new test run with the minimum amount of required fields.  You may have different required fields in your ALM project, so you might need to tweak the XML a bit.

Request Type:  POST

Header:
ContentType = “application/xml”
Accept = “application/xml”

Cookie Container:

  • LWSSO_COOKIE_KEY
  • QCSession
  • ALM_USER
  • XSRF-TOKEN

URI:

http://targetserver:targetport/qcbin/rest/domains/ALMDomain/projects/ALMProject/runs

XML:

<Entity Type='run'>
 <Fields>
 <Field Name='name'><Value>testnamegoeshere</Value></Field>
 <Field Name='test-instance'><Value>1</Value></Field>
 <Field Name='testcycl-id'><Value>testcycleidgoeshere</Value></Field> 
 <Field Name='cycle-id'><Value>cycleidgoeshere</Value></Field>
 <Field Name='test-id'><Value>testidgoeshere</Value></Field>
 <Field Name='subtype-id'><Value>hp.qc.run.MANUAL</Value></Field>
 <Field Name='status'><Value>Not Completed</Value></Field>
 <Field Name='owner'><Value>testownergoeshere</Value></Field> 
 </Fields>
</Entity>

Please note that you should set the test status as “Not Completed“.

This is the portion of the response XML that we are interested in:

 <Field Name="id"><Value>#####</Value></Field>
 <Field Name="test-config-id"><Value>#####</Value></Field>
 <Field Name="testcycl-id"><Value>#####</Value></Field>
 <Field Name="cycle-id"><Value>#####</Value></Field>
 <Field Name="test-id"><Value>#####</Value></Field>

In this response, the “id” field value refers to the “id” of the new test run.  Make sure to double check all of these values before sending the next request.

Some of these naming conventions can be confusing. This is how I identify them:

test-config-id = config ID from testlab [column name = Configuration: ID]
testcycle-id = this is the test instance ID [from Step 3]
cycle-id = this is the test set ID [right-click on testset to get this]
test-id = test ID from testlab [column name = Configuration: Test ID]

5) Update the new testrun in testlab

The most important thing to remember here is that you should set the pass/fail test status during this PUT request, not the previous POST request.  When you update the status of the test run as part of this PUT request, the status of the test instance gets updated automatically.

If you attempt to POST a new test run and pass/fail it at the same time, the test instance will not get updated with the status of the latest run.  It is possible to update the test instance directly.  I would not recommend doing this because this will create a duplicate fast run.  If you are running lots of tests, you don’t want the results to get cluttered with fast runs.

Request Type:  PUT

Header:
ContentType = “application/xml”
Accept = “application/xml”

Cookie Container:

  • LWSSO_COOKIE_KEY
  • QCSession
  • ALM_USER
  • XSRF-TOKEN

URI:

http://targetserver:targetport/qcbin/rest/domains/ALMDomain/projects/ALMProject/runs/#####

XML:

<Entity Type='run'>
 <Fields>
 <Field Name='test-instance'><Value>1</Value></Field>
 <Field Name='execution-date'><Value>yyyy-mm-dd</Value></Field>
 <Field Name='ver-stamp'><Value>1</Value></Field>
 <Field Name='test-config-id'><Value>configidgoeshere</Value></Field>
 <Field Name='name'><Value>testnamegoeshere</Value></Field>
 <Field Name='has-linkage'><Value>N</Value></Field>
 <Field Name='testcycl-id'><Value>testcycleidgoeshere</Value></Field>
 <Field Name='cycle-id'><Value>cycleidgoeshere</Value></Field>
 <Field Name='host'><Value>machinenamegoeshere</Value></Field>
 <Field Name='status'><Value>Passed</Value></Field>
 <Field Name='test-id'><Value>testidgoeshere</Value></Field>
 <Field Name='subtype-id'><Value>hp.qc.run.MANUAL</Value></Field>
 <Field Name='draft'><Value>N</Value></Field>
 <Field Name='duration'><Value>0</Value></Field>
 <Field Name='owner'><Value>testownergoeshere</Value></Field>
 </Fields>
</Entity>

6) Logout

Logout and kill the active ALM session when done.

Request Type:  GET

Header:  N/A

Cookie Container:  N/A

URI:

http://targetserver:targetport/qcbin/authentication-point/logout

XML:  N/A

Once your code is refined, you can build a DLL, JAR, etc and and have your test framework pass in arguments like test project, test ID, test status, test owner, etc

27 thoughts on “HP ALM REST API

  1. Hello,
    Thank you for this article: very useful for beginner like me 😉
    Could you provide an example on how to add test case (test case already exists in test plan) in test set via REST API?
    Thank’s

    Like

  2. Hello,
    Thank you for this article.

    I’ve an unrelated question to this topic. I’m aware that we can use the REST API’s GET method to retrieve the Project List Items (qcbin/rest/domains/…/customization/used-lists?id=XXXX).

    Is it possible to update the customization -> Project List Items using the REST API? I tried invoking the REST URL through PUT and POST methods, but getting method not support response. Any help will be much appreciated! Thank You

    Like

    • Please take a look at the ALM REST API documentation, specifically under the “Customization Resources — used-lists collection”.

      The GET method returns the project lists. The PUT, DELETE, and POST methods are all listed as N/A. Maybe these methods will be added in a future version.

      Like

  3. Hey Lobsta, great example, but not quite what I’m looking for. I see a lot of examples working with test sets, but what I’m looking for is a way to retrieve a test case (i.e. from test plan.) Could you possibly point me in the right direction for that?
    I’ll def. come back to this later if we start using test sets.

    Like

  4. HI,
    I was trying to update test status in ALM using Java and Rest API. I have one though ALM help for api and its very confusing. I get an error as : “Unknown Host Exception”. not sure which end is the problem?. can you help?

    Like

  5. Thanks for Article..I am able to Connect to ALM and get the service response. I don’t see the test case name in response .Below is response . Can you please let me know how can i get test case name. I need to compare the test case name first and then fetch the id to update the results/

    [{“Name”:”user-05″,”values”:[{“value”:”2019-08-09″}]},
    {“Name”:”user-04″,”values”:[{}]},
    {“Name”:”user-03″,”values”:[{}]},
    {“Name”:”user-02″,”values”:[{“value”:”2019-08-07″}]},
    {“Name”:”test-instance”,”values”:[{“value”:”1″}]},
    {“Name”:”user-01″,”values”:[{}]},
    {“Name”:”eparams”,”values”:[{}]},
    {“Name”:”testcycle-ver-stamp”,”values”:[{“value”:”9″}]},
    {“Name”:”user-08″,”values”:[{}]},
    {“Name”:”user-07″,”values”:[{“value”:”2019-08-07″}]},
    {“Name”:”user-25″,”values”:[{}]},
    {“Name”:”user-06″,”values”:[{“value”:”–“}]},
    {“Name”:”plan-scheduling-date”,”values”:[{“value”:”2019-08-05″}]},
    {“Name”:”plan-scheduling-time”,”values”:[{}]},
    {“Name”:”id”,”values”:[{“value”:”114″}]},
    {“Name”:”os-config”,”values”:[{}]},
    {“Name”:”host-name”,”values”:[{}]},
    {“Name”:”data-obj”,”values”:[{}]},
    {“Name”:”test-config-id”,”values”:[{“value”:”1061″}]},
    {“Name”:”has-linkage”,”values”:[{“value”:”N”}]},
    {“Name”:”pinned-baseline”,”values”:[{}]},
    {“Name”:”exec-date”,”values”:[{“value”:”2019-08-07″}]},
    {“Name”:”cycle-id”,”values”:[{“value”:”201″}]},
    {“Name”:”cycle”,”values”:[{}]},
    {“Name”:”last-modified”,”values”:[{“value”:”2019-08-07 21:18:48″}]},
    {“Name”:”exec-time”,”values”:[{“value”:”21:18:48″}]},
    {“Name”:”assign-rcyc”,”values”:[{}]},
    {“Name”:”status”,”values”:[{“value”:”Passed”}]},
    {“Name”:”iterations”,”values”:[{}]},
    {“Name”:”exec-event-handle”,”values”:[{}]},
    {“Name”:”actual-tester”,”values”:[{“value”:”TestName”}]},
    {“Name”:”attachment”,”values”:[{“value”:”Y”}]},
    {“Name”:”test-id”,”values”:[{“value”:”61″}]},
    {“Name”:”subtype-id”,”values”:[{“value”:”hp.qc.test-instance.MANUAL”}]},
    {“Name”:”test-order”,”values”:[{“value”:”1″}]},
    {“Name”:”owner”,”values”:[{“value”:”TestName”}]},
    {“Name”:”bpta-change-awareness”,”values”:[{}]}]

    Like

    • I don’t use QC/ALM anymore so I don’t know if “test case name” is a system field or a user defined field.
      In you example, this does not look valid: {“Name”:”owner”,”values”:[{“value”:”TestName”}]},

      If “test case name” is a system defined field, you need to find out the correct field name.
      If “test case name” is a user defined field, the field name most likely will look something like “user-##”.

      Like

  6. In Rest API i tried the below using the GET method.
    URL: https://*********/qcbin/rest/DOMAINPATH******/tests?query={owner[myName]}”).
    Here am getting the below error message
    java.lang.IllegalArgumentException: Invalid number of path parameters. Expected 1, was 0. Undefined path parameters are: owner[MyName]
    Method am using.
    public static Response getCallWithHeaderParamSCookies(Map headers, Map cookies, String URL) {

    LoggerUtil.log(“GET call on endpoint ” + URL + ” with headers ” + headers.entrySet());
    return given().relaxedHTTPSValidation().headers(headers).cookies(cookies).request().when()
    .get(URL);
    }

    Like

  7. Hello,

    thank you for the detailed article.

    I have a question about test creation in test plan. I am trying to create a test case in test plan – I have created an XML string with all the required fields and I try to create it with POST method. However I always get the following error:

    qccore.general-errorBad Request

    Authentication can’t be the problem, maybe I have some syntax error? I am not sure, because my XML seems good.

    Could you provide please an example for this method as well? (to create a test case in test plan)

    Thank you in advance!

    Like

  8. Hi, Thanks for this wonderful post. It is very helpful.
    I have created run instance successfully and I am able to update the run instance to “Passed” but status is not getting updated in Test Lab. What could be the reason for this?.
    Before creating run instance, what should be the status of the test instance in test lab.

    Like

  9. Hi,
    thank you for the post. It helped a lot.
    Is it possible to upload documents to the test run via API.can u help on this
    Thanks in advance

    Like

    • I am glad the post helped. I haven’t used QC/ALM in a few years, so I don’t know how to upload documents. There is probably an API call to do this, your best bet is to check the official API documentation.

      Like

Leave a comment