Publishing JUnit Test Results

The junit step (JUnit 48,319 plugin 1428.vef95b_fa_89508) parses JUnit XML, the de facto exchange format that Node's junit reporter, Jest 62,362 , pytest, Maven 129 and most other runners can write. It sits in the Test stage's post { always { ... } }, so results are recorded even when the tests fail, which is when they matter. For the branch's first build, the JSON API shows what it recorded:

The failing test in feature/id-range, build 1Groovy
F=http://localhost:32080/job/booknest/job/feature%252Fid-range
curl -s -u "admin:$JENKINS_TOKEN" -g \
  "$F/1/testReport/api/json?tree=passCount,failCount,suites[cases[name,status]]" \
  | jq -r '"pass \(.passCount), fail \(.failCount)",
           (.suites[].cases[] | select(.status != "PASSED") | "\(.status): \(.name)")'
Output
pass 8, fail 1
FAILED: GET /api/books/:id returns 404 for an unknown id

The job's name is feature%2Fid-range, hence %252F in the URL. The Tests page adds the assertion (actual: 400, expected: 404). When tests fail but the command exits 0, junit marks the build UNSTABLE; here node --test exited with 1, so the sh step failed the build first.