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:
- Authentication
- Create a new session
- Using a testset ID to return a list of test ID’s
- Create a new testrun in testlab
- Update the new testrun in testlab
- 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”
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
Hi,
I am not able retrieve the test case(test instances id) which is used in step3
LikeLike
Did you authenticate correctly ? What does your GET request look like ? What are you seeing in the response ?
LikeLike
I am able to list to test instance Id. Anyways to update the xml file dynamically
LikeLike
Yes, I am able to authenticate.
Now I need to update the xml file dynamically in Java. Can you provide any links for it.
Thank you
LikeLike
You do not need XML for the GET request. You will need to create dynamic XML for subsequent requests. There are many ways to do this with java, please search for Document and DocumentBuilder examples.
LikeLike
Ok.. will do.
Thank you for your timely support.
LikeLike
Can you provide the xml to do test step update
LikeLike
XML requests needed to create and update the test run are in the blog post (please see step 4 and step 5)
LikeLike
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
LikeLike
First query an existing test-set to see the expected XML format.
Method: GET
http://targetserver:targetport/qcbin/rest/domains/ALMDomain/projects/ALMProject/test-sets/yourtestsetid
Then create an XML payload with your testcase data and submit to this URI.
Method: PUT (to update an existing testset)
http://targetserver:targetport/qcbin/rest/domains/ALMDomain/projects/ALMProject/test-sets/yourtestsetid
Method: POST (to create a new testset)
http://targetserver:targetport/qcbin/rest/domains/ALMDomain/projects/ALMProject/test-sets/
For more info and examples, please check out the official HP ALM REST API documentation.
LikeLike
Thank you very much. It works!!!
LikeLike
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
LikeLike
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.
LikeLike
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.
LikeLike
I found the answer I was looking for, which is:
http://SERVERNAME:PORTNUMBVER/qcbin/rest/domains/DOMAINNAME/projects/PROJECTNAME/tests?login-form-required=y
LikeLike
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?
LikeLike
The message “Unknown Host Exception” can be caused by a number of things. Make sure that you are pointing to the correct server. Also double check the active entries in your host file.
LikeLike
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”:[{}]}]
LikeLike
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-##”.
LikeLike
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);
}
LikeLike
The issue is java.lang.IllegalArgumentException: Invalid number of path parameters. Expected 1, was 0. It is expecting you to supply a parameter which you have not included.
LikeLike
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!
LikeLike
The issue is in the error response = “BadRequest”. Please make sure that your XML is valid, formatted correctly, and contains all required fields.
LikeLike
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.
LikeLike
Please reread the entire post, the solution to this is clearly explained.
LikeLike
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
LikeLike
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.
LikeLike