How to integrate Katalon automation test results with Qase Test Management

Hi everyone,
I’m looking to integrate my Katalon Studio test results with Qase (a test management tool). I understand that there’s no official plugin available for this integration, but I believe it should be possible using Qase’s API.
Could anyone guide me on how to achieve this, or share an example of how you’ve done it via API? Any help would be greatly appreciated!

1 Like

step-by-step guide to integrating Katalon Studio test results with Qase via its API:

1. Prepare Qase API Access

  • Get Qase API Token:
    1. Go to Qase > Settings > API Tokens.
    2. Generate a new token with permissions for Test Runs and Results.
  • Note Your Project Code:
    • Find your project code in Qase’s URL (e.g., PRJCODE in https://app.qase.io/project/PRJCODE).

2. Configure Katalon to Generate JUnit Reports

Katalon can export results in JUnit format, which you’ll parse and send to Qase.

  1. In your test suite, enable JUnit reporting:
  • Go to Project > Settings > Report > Export as JUnit Report.
  • Check Enable JUnit Report and specify the output folder (e.g., Reports/JUnit).

3. Map Katalon Tests to Qase Test Cases

Link Katalon test cases to Qase IDs using one of these methods:

  • Option 1: Add a Qase ID custom field:
    • In Katalon, use Custom Fields (in Test Cases) to store Qase case IDs (e.g., QASE_CASE_ID=123).
  • Option 2: Use tags in test case names:
    • Name Katalon test cases with Qase IDs (e.g., TestCase_QASE123).

4. Create a Post-Execution Script

Use a Groovy script in Katalon’s Listeners folder to auto-send results after test runs.

Sample Script:

import groovy.xml.XmlSlurper
import com.kms.katalon.core.util.KeywordUtil
import java.net.http.HttpClient
import java.net.http.HttpRequest
import java.net.http.HttpResponse
import java.net.URI

class QaseIntegrationListener {
  // Qase API Configuration
  static final String QASE_API_TOKEN = "YOUR_API_TOKEN"
  static final String QASE_PROJECT_CODE = "PRJCODE"
  static final String JUNIT_REPORT_PATH = "Reports/JUnit/TEST-*.xml"

  @AfterTestSuite
  void afterTestSuite(TestSuiteContext context) {
    // Parse JUnit Report
    def junitReports = new File(getReportDir()).listFiles({ it.name.matches("TEST-.*\\.xml") } as FilenameFilter)
    junitReports.each { reportFile ->
      def xml = new XmlSlurper().parse(reportFile)
      xml.testcase.each { testcase ->
        // Extract Qase ID (e.g., from test case name: "Test_QASE123")
        def qaseCaseId = testcase.@name.text().split("_QASE").last()
        def status = (testcase.failure.isEmpty()) ? "passed" : "failed"
        
        // Send result to Qase API
        sendResultToQase(qaseCaseId, status)
      }
    }
  }

  void sendResultToQase(String caseId, String status) {
    // Create a test run first if needed (or reuse an existing one)
    def runId = createTestRun("Katalon Run ${new Date()}")

    // Post result to run
    def client = HttpClient.newHttpClient()
    def request = HttpRequest.newBuilder()
      .uri(URI.create("https://api.qase.io/v1/result/${QASE_PROJECT_CODE}/${runId}"))
      .header("accept", "application/json")
      .header("Token", QASE_API_TOKEN)
      .header("Content-Type", "application/json")
      .POST(HttpRequest.BodyPublishers.ofString(
        """
        {
          "case_id": ${caseId},
          "status": "${status}"
        }
        """
      ))
      .build()

    def response = client.send(request, HttpResponse.BodyHandlers.ofString())
    KeywordUtil.logInfo("Qase API Response: ${response.body()}")
  }

  String createTestRun(String runName) {
    def client = HttpClient.newHttpClient()
    def request = HttpRequest.newBuilder()
      .uri(URI.create("https://api.qase.io/v1/run/${QASE_PROJECT_CODE}"))
      .header("accept", "application/json")
      .header("Token", QASE_API_TOKEN)
      .header("Content-Type", "application/json")
      .POST(HttpRequest.BodyPublishers.ofString(
        """
        {
          "title": "${runName}",
          "cases": [${getAllQaseCaseIds().join(",")}]
        }
        """
      ))
      .build()

    def response = client.send(request, HttpResponse.BodyHandlers.ofString())
    def responseJson = new groovy.json.JsonSlurper().parseText(response.body())
    return responseJson.result.id
  }
}

5. Run Tests and Verify Integration

  1. Execute your test suite in Katalon.
  2. Check the Console for API responses.
  3. Verify results in Qase under Test Runs.

6. Alternative: Use CI/CD Pipeline

Example for Jenkins/GitLab:

# GitLab CI Example
stages:
  - test
  - report

katalon_test:
  stage: test
  script:
    - ./katalon -noSplash -runMode=console -projectPath="$(pwd)/YourProject.prj" -retry=0 -testSuitePath="Test Suites/YourSuite" -browserType="Chrome"

report_to_qase:
  stage: report
  script:
    - curl -X POST "https://api.qase.io/v1/run/PRJCODE" -H "Token: $QASE_TOKEN" -H "Content-Type: application/json" --data "@junit_report.xml"

Key Notes

  • Rate Limits: Qase API has limits (~30 requests/minute). Use bulk endpoints if needed.
  • Error Handling: Add retry logic for failed API calls.
  • Attachments: Use Qase’s /attachment API to upload screenshots from Katalon.

For bulk imports, consider converting JUnit reports to Qase’s format:

{
  "results": [
    { "case_id": 123, "status": "passed" },
    { "case_id": 456, "status": "failed" }
  ]
}