Helix ALM
Helix ALM provides the ability to automate tasks and integrate with other tools via REST API calls from a secured connection. You can create, update, or query the records (test case, requirement, test run, issues, and so on) from the API and receive a response in JSON format for each call.
You can integrate Perfecto with Helix ALM to view the status of automated tests run in Perfecto in Helix ALM and receive a link to the report created by Perfecto Smart Reporting in the ALM notes section.
For more information about working with Helix ALM, see https://help.perforce.com/helix-alm/helixalm/.
On this page:
Step-by-step instructions
Click a step to view details.
Invoking REST API calls requires a secured token to be generated at Helix server to pass in the header request. This token is tied to the Helix ALM project, meaning that a token generated for project-1 does not apply to project-2. The following code connects to the Helix ALM server, gets a list of projects and their associated IDs, and generates a token.
Sample code
public String connectHelixALM(String HELIX_USERNAME, String HELIX_PASSWORD, String HELIX_PROJECT) throws IOException, KeyManagementException, NoSuchAlgorithmException {
// To Trust all server side certificates
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; }
public void checkClientTrusted(X509Certificate[] certs, String authType) { }
public void checkServerTrusted(X509Certificate[] certs, String authType) { }
} };
// Install the all-trusting trust manager
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
// Create all-trusting host name verifier
HostnameVerifier allHostsValid = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) { return true; }
};
// Install the all-trusting host verifier
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
String userCredentials = HELIX_USERNAME + ":" + HELIX_PASSWORD;
String basicSecurity = new String(Base64.getEncoder().encode(userCredentials.getBytes()));
String basicAuth = "Basic " + basicSecurity;
// REST API call to extract Project ID: https://<helix_server_host>:<helix_server_port>/helix-alm/api/v0/projects
URL url1 = new URL(HELIX_BASE_URL + "/projects");
URLConnection con1 = url1.openConnection();
con1.setRequestProperty("Authorization", basicAuth);
ObjectMapper mapper1 = new ObjectMapper();
JsonNode jsonMap1 = mapper1.readTree(con1.getInputStream());
String projectId = null;
for (final JsonNode objNode : jsonMap1.withArray("projects")) {
if(objNode.get("name").textValue().equalsIgnoreCase(HELIX_PROJECT)) {
projectId = objNode.get("id").toString();
}
}
// REST API call to generate security Token: https://<helix_server_host>:<helix_server_port>/helix-alm/api/v0/{projectId}/token
URL url2 = new URL(HELIX_BASE_URL + "/" +projectId+ "/token");
URLConnection con2 = url2.openConnection();
con2.setRequestProperty("Authorization", basicAuth);
ObjectMapper mapper2 = new ObjectMapper();
JsonNode jsonMap2 = mapper2.readTree(con2.getInputStream());
String token = jsonMap2.get("accessToken").toString();
System.out.println("ACCESS TOKEN: " + token);
return token;
}
The following code generates a test run accepting the arguments testCaseId,
token
, testReport
(the test report URL), and testStatus
. It updates the newly generated test run with details sent from the request. Call the below function with test report URL and test status values that can be retrieved from the Perfecto execution run to update the link in Helix ALM.
public static int generateTestRunFromTestCase(int testCaseId, String token, String testReport, String testStatus) throws KeyManagementException, NoSuchAlgorithmException, IOException {
if(token==null) {
Documenting hu = new Documenting();
hu.connectHelixALM(HELIX_USERNAME,HELIX_PASSWORD, HELIX_PROJECT);
}
// REST API call to generate a test run for the TestCaseId: https://<helix_server_host>:<helix_server_port>/helix-alm/api/v0/{projectId}/testRuns/generate
URL url = new URL(HELIX_BASE_URL + "/"+projectId+"/testRuns/generate");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
con.setRequestProperty("Content-Type", "application/json; charset=utf-8");
con.setRequestProperty("Authorization", "Bearer " + token);
con.setRequestProperty("Accept", "application/json");
con.setDoOutput(true);
String testRunPayload = "{\n" + " \"testCaseIDs\": [" + testCaseId + "],\n" + " \"eventsData\" : [ { \"name\" : \"" + testStatus
+ "\", \"fields\" : [{ \"label\" : \"Notes\", \"string\" : \""+testReport+"\" }] } ]\n" + "}";
try (OutputStream os = con.getOutputStream()) {
byte[] input = testRunPayload.getBytes("utf-8");
os.write(input, 0, input.length);
}
ObjectMapper mapper = new ObjectMapper();
JsonNode jsonMap = mapper.readTree(new InputStreamReader(con.getInputStream(), "utf-8"));
System.out.println("\nGENERATE TEST RUN RESPONSE ===> " + jsonMap);
String testRunGeneratedId = jsonMap.get("testRuns").findValue("id").toString();
System.out.println("Test Run Id: " + testRunGeneratedId);
return Integer.parseInt(testRunGeneratedId);
}
The following code with function updateTestRunWithStepsUpdate()
updates the status of each step in the test run by marking it pass
or fail
. (The input for these statuses can be captured from the framework's step response if it uses the BDD model and updated accordingly.) The payload (JSON) of each test run is different when making the API call. It requires to fetch the correct payload before sending the update request. Function getTestRunSteps()
returns the payload for the testrunID
passed as an argument.
public static void updateTestRunWithStepsUpdate(int testRunId, String token) throws KeyManagementException, NoSuchAlgorithmException, IOException, InterruptedException {
if(props.getString("helix.token")==null) {
Documenting hu = new Documenting();
hu.connectHelixALM(HELIX_USERNAME,HELIX_PASSWORD, HELIX_PROJECT);
}
// REST API call to update a test run's steps status: https://<helix_server_host>:<helix_server_port>/helix-alm/api/v0/{projectId}/testRuns/{testRunId}/steps
URL url = new URL(HELIX_BASE_URL + "/"+projectId+"/testRuns/"+testRunId+"/steps");
HttpURLConnection con = (HttpURLConnection)url.openConnection();
con.setRequestMethod("PUT");
con.setRequestProperty("Content-Type", "application/json; charset=utf-8");
con.setRequestProperty ("Authorization", "Bearer "+token);
con.setRequestProperty("Accept", "application/json");
con.setDoOutput(true);
// This call is required to retrieve the test run's json response which is used to update before sending the actual step update API call
String jsonInputString = getTestRunSteps(testRunId, token);
// Payload, StepDetails, StepResult, User, are all POJOs created to manipulate the payload response received from getTestRunSteps API call
Payload payloadObj = new ObjectMapper().readValue(jsonInputString, Payload.class);
payloadObj.setSelf(null);
List<StepDetails> stepDetails = payloadObj.getStepsData().getDetailed();
int step = 0;
for (StepDetails stepDetail : stepDetails) {
++step;
if(stepDetail.getStep().getNumber() == 1 || stepDetail.getStep().getNumber() == 2) {
StepResult stepResult = new StepResult();
User user = new User();
user.setId(step);
user.setFirstName("System");
user.setLastName("Administrator");
user.setMi("");
user.setUsername("administrator");
stepResult.setUser(user);
stepResult.setDateTime((new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", new Locale("en", "US")).format(new Date())));
stepResult.setResult("passed");
stepDetail.getStep().setStepResult(stepResult);
}
}
System.out.println(new ObjectMapper().writeValueAsString(payloadObj));
try(OutputStream os = con.getOutputStream()) {
byte[] input = new ObjectMapper().writeValueAsString(payloadObj).getBytes("utf-8");
os.write(input, 0, input.length);
}
try(BufferedReader br = new BufferedReader(
new InputStreamReader(con.getInputStream(), "utf-8"))) {
StringBuilder response = new StringBuilder();
String responseLine = null;
while ((responseLine = br.readLine()) != null) {
response.append(responseLine.trim());
}
System.out.println("\nGenerate Test Run With Steps update Response ===>" +response.toString());
System.out.print(con.getResponseCode());
System.out.println(con.getResponseMessage());
} catch(Exception e) {
System.out.println(con.getResponseCode());
System.out.println(con.getResponseMessage());
}
}
public static String getTestRunSteps(int testRunId, String token) throws IOException, KeyManagementException, NoSuchAlgorithmException, InterruptedException {
if(token==null) {
Documenting hu = new Documenting();
hu.connectHelixALM(HELIX_USERNAME,HELIX_PASSWORD, HELIX_PROJECT);
}
// REST API call to retrieve the test run's json payload: https://<helix_server_host>:<helix_server_port>/helix-alm/api/v0/{projectId}/testRuns/{testRunId}/steps
URL url = new URL(HELIX_BASE_URL + "/"+projectId+"/testRuns/"+testRunId+"/steps");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
con.setRequestProperty("Authorization", "Bearer " + token);
con.setRequestProperty("Accept", "application/json");
ObjectMapper mapper = new ObjectMapper();
JsonNode jsonMap = mapper.readTree(new InputStreamReader(con.getInputStream(), "utf-8"));
System.out.println("\nGENERATED TEST RUN STEP RESPONSE ===> " + jsonMap);
return jsonMap.toString();
}
Sample Quantum project
You can find a sample Quantum project in GitLab: https://gitlab.com/perfectops/helixalm_perfecto_integration
With the help of custom fields, you can enable the execution report in the Perfecto Report Library to display the related test case.