n98/junit-xml
n98/junit-xml is a lightweight PHP library for building JUnit XML reports. It offers a simple API to define test suites and cases with failures, errors, skipped tests, and timing, making it easy to generate CI-friendly XML output from custom test runners.
testsuites / testsuite / testcase nesting, failure vs. error semantics, skipped, time attributes, CDATA/escaping, and the fact that every consumer parses slightly differently. Buying a ~small library beats maintaining a bespoke serializer that only one engineer understands. Recommendation: buy, but wrap it behind our own TestReportWriter interface so the dependency is replaceable in an afternoon.Adopt when:
Look elsewhere when:
--log-junit / JUnit logger and skip the dependency entirely.NOASSERTION means legal must review before this ships in a distributed or customer-facing artifact. If it can't be cleared quickly, write the ~200 lines in-house.Adoption guardrails: pin an exact version, isolate behind an interface, add a conformance test that validates output against the schema and against at least two real CI consumers, and document the fallback plan.
To executives: This is a small, cheap enabler for CI interoperability. It lets us publish test and check results in the format every CI system already understands, which removes a common enterprise objection ("does it integrate with our pipeline?") without building per-vendor connectors. Cost is a few engineering days; risk is contained because we isolate it behind our own interface and can replace it without touching product code. The one open item is license clearance, which legal should confirm before it appears in anything customer-facing.
To engineering: It's a thin, framework-agnostic JUnit XML writer — no Laravel coupling, usable from an artisan command or queued job. Use it only where we're producing results outside PHPUnit; inside PHPUnit, use the built-in logger. Wrap it in a TestReportWriter interface, pin the version, and add a schema-conformance test plus a smoke test against Jenkins and GitLab CI parsers. Assume the library could go unmaintained — the adapter boundary is the insurance policy. Flag NOASSERTION to legal early; if clearance stalls, the fallback is a short in-house serializer against the same interface.
How can I help you explore Laravel packages today?