Documentation

TestNod documentation

Learn how to set up TestNod and configure it to help you spot flaky tests, catch regressions, and see how performance changes over time.

JUnit XML format support for CI test reports

JUnit XML has a long history and many dialects. TestNod reads the elements and attributes that virtually every test runner produces, and anything else is ignored rather than rejected, so a report with vendor-specific extensions still uploads cleanly.

Document structure

TestNod accepts the standard <testsuites> and <testsuite> root forms. Both single-suite and multi-suite documents work:

<testsuites>
  <testsuite name="UserSpec" tests="3" failures="1" errors="0" skipped="1" time="0.42">
    <testcase classname="UserSpec" name="creates a user" time="0.10"/>
    <testcase classname="UserSpec" name="rejects invalid emails" time="0.12">
      <failure type="RSpec::Expectations::ExpectationNotMetError" message="expected: false">
        ...
      </failure>
    </testcase>
    <testcase classname="UserSpec" name="future feature" time="0.00">
      <skipped/>
    </testcase>
  </testsuite>
</testsuites>

Elements TestNod reads

Element What's used
<testsuite> name becomes the suite name. time is read for suite duration when present, otherwise summed from cases.
<testcase> classname and name together form the case identity used for diffs and failure clustering. time is the per-case duration.
<failure> Marks the case as failed. type and message are stored and feed the failure signature. The element body is stored as the failure trace.
<error> Marks the case as errored (test setup blew up rather than an assertion failing). Same fields as <failure>.
<skipped> Marks the case as skipped. Skipped counts feed the skipped test count creep alert.
<system-out>, <system-err> Stored as the test suite's captured output and shown on the test suite detail panel.
<properties> Each child <property> is stored as a name/value pair and shown on the test suite detail panel.

How TestNod resolves test status

Each <testcase> resolves to exactly one status, in this priority order:

  1. <error> present → errored
  2. <failure> present → failed
  3. <skipped> present → skipped
  4. Otherwise → passed

A case with both <failure> and <error> is recorded as errored.

Identity for diffs and clustering

Two test cases are "the same case across runs" when their classname and name match exactly, including whitespace. If your test runner mangles either value across runs (some Jest configurations include a path with a hash, for example), comparisons and clustering will treat them as different cases. The fix is to stabilize the identity in the runner, not in TestNod.

What's ignored

These show up in some dialects and are silently dropped:

  • Custom attributes on <testsuite> or <testcase> beyond the ones listed above.
  • Vendor-specific elements (Maven Surefire's <rerunFailure>, for example).
  • XML comments and processing instructions.

Ignored fields do not cause the upload to fail. If you depend on a field that is currently ignored, email [email protected] and the TestNod team will look at supporting it.

Character encoding

TestNod expects UTF-8 input. Most runners default to UTF-8, but some Java tools emit UTF-16 with a BOM. Convert to UTF-8 before upload if you see encoding errors during parsing.

Be first to try TestNod

We're opening early access soon. Drop your email and we'll get you in, and we're happy to help you set up too.

No spam. We'll only email you about TestNod.