Neatbo.

JUnit offline test report

Read local JUnit XML results, distinguish testcase outcomes from declared counters and download every failure and log in an offline report.

Browser-local processingInputJUnit XML filesOutputOffline HTML / JSON / CSVUp to 5 MiB per file · File limit: 20
  1. 1Add input
  2. 2Adjust settings
  3. 3Get your result

Tool input and files are processed in this browser without being uploaded.

Your input

Inputs are kept temporarily in this tab when switching tools. Refreshing or closing clears them; large results may need to be regenerated.

⌘ / Ctrl + Enter to run

or drag and drop them here

Files stay on this device. Your originals stay unchanged.

.xml

Up to 5 MiB per file · File limit: 20

    0 characters · 0 bytes
    Options

    Complete the required options first. You can keep the defaults for the rest.

    Preparing the tool…

    Before you start

    Turn exported CI test XML into a readable report without running tests. Keep nested suite paths, repeated testcase names, multiple failure events and literal logs together with the original files.

    How to use this tool

    1. Open one or several exported JUnit XML files, or paste one document.
    2. Review case outcomes, mixed events, nested paths and separately declared suite counters.
    3. Download the full offline HTML, JSON/CSV; retain the original input separately.

    Supported inputs and limits

    Up to 20 UTF-8 files, each 5 MiB and 10 MiB combined, or one pasted XML up to 5 MiB. Across the input: 10,000 testcases, 50,000 XML element nodes and 64 element levels. Selected files take precedence. Combined downloads up to 10 MiB; an oversized complete report rejects atomically. Table preview first 200 cases.

    Supports nested testsuites/testsuites and testsuite/testcase, failure/error/skipped events, ordinary properties and system-out/system-err. A testcase may have multiple events; it counts once in summary. Multiple outcome kinds are explicitly mixed. Duplicate names remain separate indexed cases, without merging.

    Accepted testcase attributes: name, classname, time, assertions, file, line, url and id. Unknown outcome elements or attributes, flaky/rerun extensions, DTD and external entities reject. Empty suites must explicitly declare tests="0". Correct or re-export unsupported producer data; it is never labelled passed.

    Declared suite/container counters and time stay separate from testcase counts. measuredSeconds sums testcase times only if every case supplies a finite nonnegative time; otherwise null/unknown. This sum is not suite wall time. HTML escapes all text and has no script/source fetching. JSON retains every event, suite log and property; CSV retains every case, with optional formula protection. Keep the original XML beside the report; it is not copied into downloads.

    The result text and copy action use a compact preview when the report exceeds 20,000 characters. Complete report.json, CSV and HTML are downloaded artifacts. Long table cells show only their first 2,000 characters plus ellipsis; complete downloads are not truncated.

    Worked example

    Example input

    <testsuites tests="3" time="99"><testsuite name="unit" tests="3" failures="1" skipped="1"><testcase name="ok" time="0.1"/><testcase name="fails" time="0.2"><failure message="expected 2">actual 1</failure><failure message="second assertion">trace</failure></testcase><testcase name="later" time="0"><skipped message="pending"/></testcase></testsuite></testsuites>
    Example options
    {"secondary":"","params":{"spreadsheetSafe":true}}

    Example output

    {"format":"JUnit XML scoped report","summary":{"files":1,"suites":1,"cases":3,"passed":1,"failure":1,"error":0,"skipped":1,"mixed":0,"events":3,"measuredSeconds":0.30000000000000004,"measuredCaseTimes":3,"xmlNodes":8},"sourceFiles":["pasted.xml"],"containers":[{"file":0,"path":[],"attributes":{"tests":"3","time":"99"},"logs":[],"properties":[],"caseIndices":[0,1,2]}],"suites":[{"file":0,"path":["unit"],"attributes":{"name":"unit","tests":"3","failures":"1","skipped":"1"},"logs":[],"properties":[],"caseIndices":[0,1,2]}],"cases":[{"index":0,"file":0,"suitePath":["unit"],"attributes":{"name":"ok","time":"0.1"},"name":"ok","classname":"","time":0.1,"outcome":"passed","events":[],"logs":[],"properties":[]},{"index":1,"file":0,"suitePath":["unit"],"attributes":{"name":"fails","time":"0.2"},"name":"fails","classname":"","time":0.2,"outcome":"failure","events":[{"tag":"failure","attributes":{"message":"expected 2"},"children":[],"text":"actual 1"},{"tag":"failure","attributes":{"message":"second assertion"},"children":[],"text":"trace"}],"logs":[],"properties":[]},{"index":2,"file":0,"suitePath":["unit"],"attributes":{"name":"later","time":"0"},"name":"later","classname":"","time":0,"outcome":"skipped","events":[{"tag":"skipped","attributes":{"message":"pending"},"children":[],"text":""}],"logs":[],"properties":[]}]}

    When something does not work

    Remove DTD/entities and check well-formed XML, supported testcase attributes/outcomes, explicit zero-test suites and finite nonnegative times. Re-export unsupported dialects with the producer. Reduce the input if the complete downloads exceed 10 MiB, then rerun.

    Frequently asked questions

    Why are three failure events not three failed tests?

    Events belong to testcases. A case with multiple failure events counts once as failure, while every event remains in detail. A case combining skipped and failure is mixed.

    Does measuredSeconds match the suite time?

    No. It sums individual case times only when all exist. Suite/container wall-clock time and counters remain producer declarations and can differ.

    Will a flaky result silently become a pass?

    No. Unknown flaky/rerun/custom outcomes reject. Export a supported result dialect or preserve the original and inspect it with its producer.

    Documentation & further reading

    Related tools