Understanding Helix Testing Integration
Helix Testing Integration refers to the systematic connection between Helix ALM (Application Lifecycle Management) — formerly known as TestTrack — and your software testing ecosystem. It bridges test management, automated test execution, continuous integration pipelines, and version control to create a unified quality assurance workflow. At its core, the integration enables teams to plan test cases, track execution results, link tests to source code changes, and generate compliance-ready audit trails — all within a single pane of glass.
The Helix ALM suite provides a REST API, webhooks, and native CI plugin interfaces that allow developers and QA engineers to push test results from any framework — JUnit, pytest, Selenium, Cypress, Playwright, or custom scripts — directly into Helix Test Management. This eliminates manual result entry, reduces human error, and accelerates feedback loops across the development lifecycle.
Key Components of the Integration
- Helix ALM Server — The central repository for test cases, test runs, requirements, and issues
- Helix ALM REST API — The programmatic interface for creating, updating, and querying test artifacts
- Helix CLI Client (tccli) — A command-line utility for batch operations and scripted interactions
- CI Plugin / Webhook Bridge — Middleware that translates CI build results into Helix test run entries
- Source Control Connector (Perforce Helix Core or Git) — Links code changes to specific test cases and requirements
Why Helix Testing Integration Matters
🚀 Deploy your AI agent in 10 minutes
Managed Hermes hosting. Zero DevOps. 100M tokens/mo included.
Try it free →Without integration, test results live in isolated silos. A CI pipeline might run 2,000 tests, produce a JUnit XML report, and then sit idle while someone manually transcribes pass/fail counts into a test management tool. That gap introduces latency, miscounts, and a loss of traceability that becomes catastrophic during audits or release sign-off. Helix Testing Integration solves this by automating the flow of data end-to-end.
Benefits at a Glance
- Real-time traceability — Every automated test result links directly to a Helix test case, which links to a requirement, which links to a code change
- Audit readiness — Industries like medical devices, aerospace, and automotive (governed by FDA, ISO 13485, DO-178C) demand proof that testing covered every requirement. Helix generates that matrix automatically
- Reduced manual overhead — QA engineers spend less time on data entry and more time on exploratory testing
- Trend analysis — Helix accumulates historical test run data, enabling pass-rate trend charts, flaky test detection, and regression risk scoring
- CI/CD pipeline gating — Test results flowing into Helix can trigger workflow transitions, such as automatically promoting a build from "Test" to "Release Candidate" when all critical tests pass
Architecture and Data Flow
Before diving into code, it's helpful to understand the typical integration architecture. The diagram below (described textually) illustrates how data moves between systems:
┌─────────────────────┐ REST API / tccli ┌──────────────────────────┐
│ CI/CD Pipeline │ ─────────────────────────▶ │ Helix ALM Server │
│ (Jenkins, GitLab, │ │ │
│ GitHub Actions, │ │ ┌────────────────────┐ │
│ Azure DevOps) │ │ │ Test Cases │ │
└─────────────────────┘ │ │ Test Runs │ │
│ │ │ Requirements │ │
│ │ │ Issues / Bugs │ │
▼ │ └────────────────────┘ │
┌─────────────────────┐ │ │
│ Test Frameworks │ │ Source Control Linkage │
│ (JUnit, pytest, │ │ (Helix Core / Git) │
│ Selenium, etc.) │ └──────────────────────────┘
└─────────────────────┘ │
│ │
▼ ▼
┌─────────────────────┐ ┌──────────────────────────┐
│ JUnit XML / JSON │ │ Helix Core / Git Repo │
│ Test Results │ │ (source code, changelists)│
└─────────────────────┘ └──────────────────────────┘
Getting Started: Prerequisites
To follow along with the code examples, ensure you have:
- A running Helix ALM Server instance (on-premises or cloud)
- API credentials with appropriate permissions (typically a dedicated service account)
- The
tcclicommand-line tool installed (available from Perforce's download portal) - A test framework producing machine-parsable output (JUnit XML, JSON, or TAP format)
- A CI/CD pipeline where you can inject shell scripts or plugin steps
Installing and Configuring tccli
The Helix Command-Line Interface client is the most versatile tool for integration. Install it on your CI build agent or developer workstation:
# Download the tccli package for your platform from Perforce's download site
# Example for Linux x64:
wget https://ftp.perforce.com/helix-alm/cli/r2024.1/tccli-r2024.1-linux-x64.tar.gz
# Extract and place on PATH
tar -xzf tccli-r2024.1-linux-x64.tar.gz
sudo cp tccli /usr/local/bin/
sudo chmod +x /usr/local/bin/tccli
# Verify installation
tccli --version
# Output: Helix ALM CLI Client version 2024.1.0
Next, configure authentication. You can use a profile file or environment variables:
# Create a configuration profile (recommended for CI environments)
tccli config --server https://helix-server.example.com:8443 \
--username svc_test_integration \
--password-file /secure/helix-password.txt \
--project "ProjectAlpha" \
--profile ci-integration
# Alternatively, use environment variables for ephemeral CI jobs
export HELIX_SERVER_URL="https://helix-server.example.com:8443"
export HELIX_USERNAME="svc_test_integration"
export HELIX_PASSWORD="$(cat /secure/helix-password.txt)"
export HELIX_PROJECT="ProjectAlpha"
Core Integration Workflows with Code Examples
Workflow 1: Creating and Executing a Test Run from CI
The most common workflow involves: (1) retrieving a predefined test suite or filter from Helix, (2) executing the tests in your pipeline, and (3) pushing results back to Helix as a completed test run.
Step 1: Query test cases from Helix using the REST API. You can filter by requirement, test folder, or labels:
# Use curl to fetch test cases that are tagged for smoke testing
curl -X GET \
"https://helix-server.example.com:8443/rest/api/v1/testcases?filter=labels%3A%22smoke%22&fields=id,name,description" \
-H "Authorization: Basic $(echo -n 'svc_test_integration:YourPassword' | base64)" \
-H "Accept: application/json" \
-o smoke_tests.json
# Sample response (smoke_tests.json):
# {
# "data": [
# {"id": "TC-1001", "name": "Login Page Smoke Test", "description": "..."},
# {"id": "TC-1002", "name": "Dashboard Load Smoke Test", "description": "..."},
# ...
# ],
# "totalResults": 12
# }
Step 2: Create a new test run in Helix, associating it with these test cases. The test run will be the container for results:
# Create a new test run via REST API
curl -X POST \
"https://helix-server.example.com:8443/rest/api/v1/testruns" \
-H "Authorization: Basic $(echo -n 'svc_test_integration:YourPassword' | base64)" \
-H "Content-Type: application/json" \
-d '{
"name": "Nightly Smoke - Build #247 - 2025-06-15",
"testcaseIds": ["TC-1001", "TC-1002", "TC-1003", "TC-1004"],
"status": "InProgress",
"buildNumber": "247",
"environment": "Staging-US-East"
}' \
-o created_run.json
# Extract the test run ID from the response
RUN_ID=$(jq -r '.id' created_run.json)
echo "Created Test Run ID: $RUN_ID"
# Output: Created Test Run ID: TR-5890
Step 3: Execute your actual tests (this is framework-dependent). The key is to produce structured output that can be parsed:
# Run pytest and generate JUnit XML output
cd /workspace/tests
pytest smoke_tests/ --junitxml=smoke_results.xml -v
# Alternatively, for a JavaScript project:
# npx playwright test --grep="@smoke" --reporter=junit --output=smoke_results.xml
Step 4: Parse the test result file and submit individual test case results to Helix. This script reads JUnit XML, maps test names to Helix test case IDs, and updates the test run:
#!/usr/bin/env python3
"""
submit_results.py - Parse JUnit XML and push results to Helix ALM
"""
import xml.etree.ElementTree as ET
import requests
import sys
import os
# --- Configuration ---
HELIX_SERVER = os.environ.get("HELIX_SERVER_URL")
HELIX_USER = os.environ.get("HELIX_USERNAME")
HELIX_PASS = os.environ.get("HELIX_PASSWORD")
RUN_ID = os.environ.get("RUN_ID") # TR-5890 from previous step
RESULTS_FILE = "smoke_results.xml"
# --- Mapping: JUnit test name -> Helix Test Case ID ---
# In practice, this mapping is derived from test annotations or a config file
TEST_CASE_MAP = {
"test_login_success": "TC-1001",
"test_login_failure": "TC-1002", # Note: two JUnit tests can map to same Helix TC
"test_dashboard_load": "TC-1003",
"test_user_profile_edit": "TC-1004",
}
def parse_junit_xml(filepath):
"""Parse JUnit XML and return a list of {name, classname, result, message} dicts."""
tree = ET.parse(filepath)
root = tree.getroot()
results = []
for testcase in root.iter('testcase'):
name = testcase.get('name')
classname = testcase.get('classname')
full_name = f"{classname}.{name}" if classname else name
# Check for failure, error, or skipped child elements
failure = testcase.find('failure')
error = testcase.find('error')
skipped = testcase.find('skipped')
if failure is not None:
result = "Failed"
message = failure.get('message') or failure.text or "Test failed"
elif error is not None:
result = "Error"
message = error.get('message') or error.text or "Test error"
elif skipped is not None:
result = "Skipped"
message = skipped.get('message') or "Test skipped"
else:
result = "Passed"
message = ""
results.append({
"name": name,
"full_name": full_name,
"result": result,
"message": message
})
return results
def update_helix_test_run_result(run_id, test_case_id, verdict, comment=""):
"""Update a single test case result within a Helix test run."""
url = f"{HELIX_SERVER}/rest/api/v1/testruns/{run_id}/results"
payload = {
"testcaseId": test_case_id,
"verdict": verdict, # "Passed", "Failed", "Error", "Skipped", "Blocked"
"actualResults": comment,
"executedBy": HELIX_USER,
"executionTime": 0 # Optional: set actual execution time in seconds
}
response = requests.post(
url,
json=payload,
auth=(HELIX_USER, HELIX_PASS),
headers={"Content-Type": "application/json"}
)
if response.status_code not in (200, 201):
print(f"ERROR updating TC {test_case_id}: {response.status_code} - {response.text}")
else:
print(f"Updated TC {test_case_id} -> {verdict}")
# --- Main Execution ---
if __name__ == "__main__":
if not RUN_ID:
print("ERROR: RUN_ID environment variable not set")
sys.exit(1)
junit_results = parse_junit_xml(RESULTS_FILE)
for test_result in junit_results:
test_name = test_result["name"]
if test_name in TEST_CASE_MAP:
tc_id = TEST_CASE_MAP[test_name]
update_helix_test_run_result(
RUN_ID,
tc_id,
test_result["result"],
test_result["message"]
)
else:
print(f"WARNING: No Helix mapping for test '{test_name}' - skipping")
print(f"Submitted {len(junit_results)} results to Helix Test Run {RUN_ID}")
Step 5: Mark the test run as complete once all results are submitted:
# Close the test run, setting its final status
curl -X PUT \
"https://helix-server.example.com:8443/rest/api/v1/testruns/TR-5890" \
-H "Authorization: Basic $(echo -n 'svc_test_integration:YourPassword' | base64)" \
-H "Content-Type: application/json" \
-d '{
"status": "Completed",
"conclusion": "Passed"
}'
Workflow 2: Using tccli for Bulk Operations
For teams that prefer shell scripting over direct REST API calls, tccli provides a simplified interface. It's ideal for CI pipelines where curl + jq may be cumbersome:
#!/bin/bash
# ci_integration.sh - Complete CI integration script using tccli
set -euo pipefail
# --- Initialize tccli session ---
tccli login --profile ci-integration
# --- Create test run and capture its ID ---
RUN_ID=$(tccli testrun create \
--name "Regression Suite - Build ${CI_BUILD_NUMBER} - $(date +%Y-%m-%d)" \
--status "InProgress" \
--filter "labels=regression" \
--project "ProjectAlpha" \
--output-format json | jq -r '.id')
echo "Created Helix Test Run: $RUN_ID"
# --- Execute tests ---
cd /app/tests
mvn test -Dtest="RegressionSuite" -DfailIfNoTests=false
# --- Submit results in batch ---
# tccli can parse JUnit XML directly and submit results
tccli testrun submit-results \
--test-run-id "$RUN_ID" \
--junit-file target/surefire-reports/TEST-RegressionSuite.xml \
--mapping-file test_case_mapping.json \
--profile ci-integration
# --- Complete the test run ---
tccli testrun update \
--test-run-id "$RUN_ID" \
--status "Completed" \
--conclusion "Passed"
echo "Test run $RUN_ID completed successfully."
The mapping file test_case_mapping.json referenced above bridges framework test names to Helix test case IDs:
{
"mappings": [
{"junitName": "com.app.RegressionSuite.testOrderCreation", "helixTC": "TC-2001"},
{"junitName": "com.app.RegressionSuite.testPaymentProcessing", "helixTC": "TC-2002"},
{"junitName": "com.app.RegressionSuite.testInventoryUpdate", "helixTC": "TC-2003"},
{"junitName": "com.app.RegressionSuite.testEmailNotification", "helixTC": "TC-2004"}
],
"defaultVerdictOnMissingMapping": "ignore"
}
Workflow 3: Webhook-Driven Integration for Event-Based Triggers
Helix ALM supports webhooks that fire on test run state changes. You can invert the flow: let Helix trigger your CI pipeline when a test run is created manually, then have the pipeline execute tests and report back. This is useful for manual test run approval workflows.
First, configure a webhook in Helix ALM Admin UI or via API:
# Register a webhook that fires when a test run enters "Ready for Execution" status
curl -X POST \
"https://helix-server.example.com:8443/rest/api/v1/webhooks" \
-H "Authorization: Basic $(echo -n 'admin:password' | base64)" \
-H "Content-Type: application/json" \
-d '{
"name": "CI Trigger Webhook",
"url": "https://jenkins.example.com/generic-webhook-trigger/invoke?token=helix-trigger",
"events": ["testrun.status.changed"],
"filter": "status=Ready for Execution",
"active": true
}'
On the CI side (Jenkins Pipeline example), receive the webhook payload and extract the test run ID:
// Jenkinsfile - Triggered by Helix webhook
pipeline {
agent any
triggers {
// Generic webhook trigger plugin
genericVariables([
key: 'helix_run_id',
value: '$.payload.testrun.id' // JSONPath to extract test run ID
])
}
stages {
stage('Checkout') {
steps {
git url: 'https://github.com/example/project.git', branch: 'main'
}
}
stage('Execute Tests') {
steps {
script {
// Fetch test cases associated with this Helix test run
def testCases = sh(
script: """
curl -s -X GET \
"https://helix-server.example.com:8443/rest/api/v1/testruns/${env.helix_run_id}/testcases" \
-u "svc_test_integration:${HELIX_PASS}" | jq -r '.data[].name'
""",
returnStdout: true
).trim()
echo "Executing Helix test cases: ${testCases}"
// Run tests matching these test case names
sh """
pytest -k "${testCases.replace('\n', ' or ')}" --junitxml=results.xml
"""
}
}
}
stage('Report Results') {
steps {
sh '''
python3 submit_results.py # Same script from Workflow 1
'''
}
}
}
}
Workflow 4: Linking Source Code Changes to Test Results
One of Helix's most powerful features is the ability to link changelists (from Helix Core or Git) directly to test cases and test runs. This provides full bidirectional traceability: you can see which code changes were tested by which test run, and vice versa.
# Example: During CI, capture the changelist or commit SHA and link it to the test run
# For Helix Core (Perforce):
CHANGELIST=$(p4 changes -m 1 -t //depot/main/... | awk '{print $2}')
# For Git:
COMMIT_SHA=$(git rev-parse HEAD)
# Link the changelist to the test run in Helix
curl -X POST \
"https://helix-server.example.com:8443/rest/api/v1/testruns/TR-5890/links" \
-H "Authorization: Basic $(echo -n 'svc_test_integration:YourPassword' | base64)" \
-H "Content-Type: application/json" \
-d "{
\"linkedItemType\": \"changelist\",
\"linkedItemId\": \"${COMMIT_SHA}\",
\"linkType\": \"TestedBy\",
\"repository\": \"ProjectAlpha-GitHub\"
}"
# You can also link individual test case results to specific changelists
# for granular traceability
curl -X POST \
"https://helix-server.example.com:8443/rest/api/v1/testcases/TC-1001/links" \
-H "Authorization: Basic $(echo -n 'svc_test_integration:YourPassword' | base64)" \
-H "Content-Type: application/json" \
-d "{
\"linkedItemType\": \"changelist\",
\"linkedItemId\": \"${COMMIT_SHA}\",
\"linkType\": \"VerifiedBy\",
\"repository\": \"ProjectAlpha-GitHub\"
}"
Advanced Integration Patterns
Pattern 1: Parallel Test Execution with Aggregated Results
When your test suite is large and runs across multiple parallel CI nodes, you need to aggregate results into a single Helix test run. The approach is to create the test run upfront, distribute test case subsets to each parallel executor, and have each executor submit results independently:
#!/bin/bash
# master_aggregator.sh - Orchestrates parallel test execution and aggregation
# Step 1: Create the master test run
RUN_ID=$(tccli testrun create \
--name "Full Regression - Build ${BUILD_NUMBER}" \
--status "InProgress" \
--filter "labels=regression" \
--output-format json | jq -r '.id')
# Step 2: Fetch all test cases for this run and split into chunks
ALL_TEST_CASES=$(curl -s \
"https://helix-server.example.com:8443/rest/api/v1/testruns/${RUN_ID}/testcases" \
-u "${USER}:${PASS}" | jq -r '.data[].id')
# Split into 4 chunks for 4 parallel workers
echo "$ALL_TEST_CASES" | split -l $(($(echo "$ALL_TEST_CASES" | wc -l) / 4 + 1)) - chunk_
# Step 3: Dispatch to parallel workers (Jenkins parallel stages, GitHub matrix, etc.)
# Each worker receives its chunk file and the RUN_ID
for CHUNK_FILE in chunk_*; do
# In a real CI setup, this would be a parallel job call
# For demonstration, we'll use background processes
(
CHUNK_TC_IDS=$(cat "$CHUNK_FILE" | tr '\n' ',')
# Execute only the tests mapped to these Helix TC IDs
pytest --helix-tc-filter="${CHUNK_TC_IDS}" --junitxml="results_${CHUNK_FILE}.xml"
# Submit results for this chunk
tccli testrun submit-results \
--test-run-id "$RUN_ID" \
--junit-file "results_${CHUNK_FILE}.xml" \
--mapping-file test_case_mapping.json
) &
done
# Wait for all parallel workers to finish
wait
# Step 4: Verify all test cases have results and close the run
PENDING_COUNT=$(tccli testrun get --test-run-id "$RUN_ID" --output-format json | \
jq '.testCases | map(select(.verdict == "NotRun")) | length')
if [ "$PENDING_COUNT" -eq 0 ]; then
tccli testrun update --test-run-id "$RUN_ID" --status "Completed" --conclusion "Passed"
else
echo "WARNING: ${PENDING_COUNT} test cases still pending - run not closed"
fi
Pattern 2: Automated Flaky Test Detection
By accumulating historical test run data in Helix, you can build a flaky test detector. The following script queries the Helix REST API for recent test case results and flags any test that shows inconsistent pass/fail patterns:
#!/usr/bin/env python3
"""
flaky_detector.py - Identify flaky tests using Helix ALM historical data
"""
import requests
from collections import defaultdict
HELIX_SERVER = "https://helix-server.example.com:8443"
USER = "svc_test_integration"
PASS = "YourPassword"
DAYS_TO_ANALYZE = 14
def get_recent_results(days=14):
"""Fetch test case results from the last N days."""
url = f"{HELIX_SERVER}/rest/api/v1/testruns/results"
# Query for completed test run results in the date range
params = {
"filter": f"executionDate>now-{days}d",
"fields": "testcaseId,verdict,testrunId",
"limit": 5000
}
response = requests.get(url, auth=(USER, PASS), params=params)
response.raise_for_status()
return response.json().get("data", [])
def detect_flaky(results):
"""Analyze results per test case and identify flaky patterns."""
tc_results = defaultdict(list)
for result in results:
tc_id = result["testcaseId"]
verdict = result["verdict"]
tc_results[tc_id].append(verdict)
flaky_candidates = []
for tc_id, verdicts in tc_results.items():
# Need at least 5 runs to establish a pattern
if len(verdicts) < 5:
continue
# Count transitions: passed->failed or failed->passed
transitions = 0
for i in range(1, len(verdicts)):
if verdicts[i] != verdicts[i-1]:
transitions += 1
# If more than 20% of consecutive runs show different results, flag as flaky
flakiness_ratio = transitions / (len(verdicts) - 1)
if flakiness_ratio > 0.2:
flaky_candidates.append({
"testcaseId": tc_id,
"flakinessRatio": round(flakiness_ratio, 2),
"totalRuns": len(verdicts),
"recentVerdicts": verdicts[-5:]
})
return sorted(flaky_candidates, key=lambda x: x["flakinessRatio"], reverse=True)
if __name__ == "__main__":
print(f"Analyzing last {DAYS_TO_ANALYZE} days of Helix test results...")
results = get_recent_results(DAYS_TO_ANALYZE)
print(f"Retrieved {len(results)} individual test case results")
flaky_tests = detect_flaky(results)
if flaky_tests:
print(f"\nFound {len(flaky_tests)} potentially flaky tests:")
print("-" * 60)
for test in flaky_tests[:10]: # Top 10
print(f"TC: {test['testcaseId']} | "
f"Flakiness: {test['flakinessRatio']} | "
f"Runs: {test['totalRuns']} | "
f"Recent: {test['recentVerdicts']}")
else:
print("No flaky tests detected in the analysis period.")
Pattern 3: Custom Dashboard and Metrics Export
Helix's REST API allows you to extract aggregate metrics for custom dashboards or integration with tools like Grafana, Power BI, or Splunk:
#!/usr/bin/env python3
"""
metrics_exporter.py - Export Helix test metrics to JSON for dashboard consumption
Outputs: test_pass_rate, requirements_coverage, open_defects, etc.
"""
import requests
import json
from datetime import datetime, timedelta
HELIX_SERVER = "https://helix-server.example.com:8443"
USER = "svc_test_integration"
PASS = "YourPassword"
def fetch_metrics():
metrics = {}
# 1. Test pass rate for the last 7 days
resp = requests.get(
f"{HELIX_SERVER}/rest/api/v1/testruns",
params={
"filter": "status=Completed and completionDate>now-7d",
"fields": "id,conclusion"
},
auth=(USER, PASS)
)
runs = resp.json().get("data", [])
passed = sum(1 for r in runs if r.get("conclusion") == "Passed")
metrics["test_run_pass_rate_7d"] = round(passed / len(runs) * 100, 1) if runs else 0
metrics["total_test_runs_7d"] = len(runs)
# 2. Requirements coverage (requirements with linked test cases)
resp = requests.get(
f"{HELIX_SERVER}/rest/api/v1/requirements",
params={
"filter": "status=Approved",
"fields": "id,linkedTestCasesCount"
},
auth=(USER, PASS)
)
reqs = resp.json().get("data", [])
total_reqs = len(reqs)
covered_reqs = sum(1 for r in reqs if r.get("linkedTestCasesCount", 0) > 0)
metrics["requirements_coverage_pct"] = round(covered_reqs / total_reqs * 100, 1) if total_reqs else 0
# 3. Open defects by severity
resp = requests.get(
f"{HELIX_SERVER}/rest/api/v1/issues",
params={
"filter": "status=Open",
"fields": "id,severity"
},
auth=(USER, PASS)
)
issues = resp.json().get("data", [])
severity_counts = {}
for issue in issues:
sev = issue.get("severity", "Unknown")
severity_counts[sev] = severity_counts.get(sev, 0) + 1
metrics["open_defects_by_severity"] = severity_counts
metrics["total_open_defects"] = len(issues)
# 4. Average test execution time
resp = requests.get(
f"{HELIX_SERVER}/rest/api/v1/testruns/results",
params={
"filter": "executionDate>now-7d",
"fields": "executionTime",
"limit": 10000
},
auth=(USER, PASS)
)
results = resp.json().get("data", [])
times = [r.get("executionTime", 0) for r in results if r.get("executionTime")]
metrics["avg_execution_time_seconds"] = round(sum(times) / len(times), 2) if times else 0
return metrics
if __name__ == "__main__":
metrics = fetch_metrics()
timestamp = datetime.utcnow().isoformat() + "Z"
output = {
"timestamp": timestamp,
"source": "Helix ALM Metrics Exporter",
"metrics": metrics
}
print(json.dumps(output, indent=2))
# Optionally write to a file for Grafana's JSON datasource or push to InfluxDB
with open("/var/metrics/helix_metrics.json", "w") as f:
json.dump(output, f, indent=2)
Best Practices for Helix Testing Integration
1. Establish a Consistent Test Case Naming Convention
Your automated tests in code must map reliably to Helix test cases. Adopt a convention that makes mapping deterministic. For example, annotate each test method with its Helix test case ID:
# Python / pytest example using custom markers
import pytest
@pytest.mark.helix_tc("TC-1001")
def test_login_success():
assert login("user@example.com", "valid_password") is True
@pytest.mark.helix_tc("TC-1002")
def test_login_failure_wrong_password():
assert login("user@example.com", "wrong_password") is False
# Then in your conftest.py, extract the marker for result submission:
# helix_tc_id = item.get_closest_marker('helix_tc').args[0]
// Java / JUnit 5 example using custom annotations
import org.junit.jupiter.api.Test;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface HelixTestCase {
String value();
}
public class LoginTests {
@Test
@HelixTestCase("TC-1001")
void testLoginSuccess() {
assertTrue(LoginService.authenticate("user@example.com", "valid_password"));
}
@Test
@HelixTestCase("TC-1002")
void testLoginFailureWrongPassword() {
assertFalse(LoginService.authenticate("user@example.com", "wrong_password"));
}
}
2. Use Service Accounts with Minimal Permissions
Create