Hawzu treats your CI/CD system as an execution engine and its report as the source of truth. Nothing reads your repository or makes assumptions about Playwright, pytest, Selenium or TestNG — if your framework can emit one of the formats below, Hawzu can import it.
One call, any format
Section titled “One call, any format”| Format | format value | Typical source |
|---|---|---|
| JUnit / xUnit XML | junit | Playwright, pytest, Jest, TestNG, Selenium, PHPUnit |
| TRX | trx | dotnet test, MSTest, Visual Studio |
| NUnit 3 XML | nunit | NUnit |
| Cucumber JSON | cucumber | Cucumber, Behave, SpecFlow, Godog |
| Allure result JSON | allure | Allure-instrumented suites |
Omit format and Hawzu detects it. Zip archives are accepted and unpacked — which is
what a GitHub Actions artifact always is, and what an Allure results directory looks like.
Choosing a mode
Section titled “Choosing a mode”The execution_id parameter decides how the run is scoped, and the difference matters.
Without execution_id — the report defines the run
Section titled “Without execution_id — the report defines the run”A new run is created containing exactly the test cases the report matched. Zero setup, ideal for a pipeline that just wants its results recorded.
The trade-off: the run’s scope is whatever the pipeline happened to contain, so it can never tell you what your automation doesn’t cover.
With execution_id — results land on a run you built
Section titled “With execution_id — results land on a run you built”Someone creates an automated test run in the app and adds the test cases the pipeline is meant to cover. The report then maps onto them:
- Cases the report covers → results applied normally.
- Cases in the run the report never mentions → left
Not Executed. This is real signal: it is the gap between what you meant to automate and what actually ran. - Report rows that aren’t in the run → returned in
unmatchedand recorded separately. They do not affect status counts, analytics, test case history or release readiness.
Mapping tests to test cases
Section titled “Mapping tests to test cases”Matching on the test’s name alone is a trap — renaming a test silently breaks it. Hawzu resolves each report row in this order:
-
An explicit Hawzu code stated by the report. The most robust option, because it survives renaming the test.
-
A code token embedded in the test name or classname, e.g.
CHK-123 logs in successfully. No tooling required — just put the code in the test title. -
An exact match on the test case title. A convenient fallback; an ambiguous title is never guessed at.
Stating the code explicitly
Section titled “Stating the code explicitly”| Format | How |
|---|---|
| JUnit | <property name="testcase_code" value="CHK-123"/> on the <testcase> (or the suite) |
| TRX | An MSTest trait named testcase_code |
| NUnit | <property name="testcase_code" value="CHK-123"/> |
| Cucumber | A scenario tag: @CHK-123 |
| Allure | A label named testcase_code, or a CHK-123 tag |
One test covering several test cases
Section titled “One test covering several test cases”An end-to-end test often stands in for several manual test cases. Name them all and each one receives the same verdict:
Or state them explicitly — as one delimited value, or as repeated properties:
If the run doesn’t contain one of the named cases, that case is listed
individually in the run’s Unmatched tab, so a partially covered test is
visible rather than quietly leaving cases Not Executed.
Worked example: Playwright
Section titled “Worked example: Playwright”Playwright is the common case, and needs no reporter plumbing — putting the code in the test title is enough.
-
Name each test with its Hawzu code.
-
Emit JUnit XML.
-
Upload the report even when tests fail —
if: always()is the part people miss. Without it a red suite skips the upload, and Hawzu reports that the build produced no readable test report.
Status mapping
Section titled “Status mapping”Results normalise to Hawzu’s statuses:
| Hawzu | Comes from |
|---|---|
Passed | A passing test |
Failed | A failure or error |
Skipped | A skipped/ignored test, or a JUnit <skipped> |
Blocked | Allure broken, NUnit/TRX Inconclusive, TRX Blocked, a Cucumber undefined/pending step — cases where the test never reached a verdict, so the feature was never actually judged |
JUnit has no way to express Blocked. To set it, add
<property name="hawzu_status" value="Blocked"/> to the test case.
When several report rows map to one test case — parametrised or retried suites — the worst status wins. A case that failed any variant is not green.
The failure message, duration and stack trace are kept as the result comment.
Response
Section titled “Response”Set on_unmatched=error to make the whole import fail with 400 when anything doesn’t
match, writing nothing. The default, skip, imports what it can and reports the rest.
Triggering builds from Hawzu
Section titled “Triggering builds from Hawzu”Everything above is CI pushing to Hawzu. Hawzu can also pull: connect Jenkins, GitHub Actions or GitLab CI under Integrations, add a pipeline under Project Settings → Automation, then create an automated test run and press Run. Hawzu triggers the build, watches it, downloads the report and imports it — no API calls of your own.
Pipelines that already run on their own schedule can notify Hawzu instead of being polled; each automation configuration exposes a signed inbound webhook URL for that.